Skip to content

fix(ndb): replace deprecated datetime.utcnow() and utcfromtimestamp() - #18186

Open
skippdot wants to merge 1 commit into
googleapis:mainfrom
skippdot:ndb-utcnow
Open

fix(ndb): replace deprecated datetime.utcnow() and utcfromtimestamp()#18186
skippdot wants to merge 1 commit into
googleapis:mainfrom
skippdot:ndb-utcnow

Conversation

@skippdot

Copy link
Copy Markdown
Contributor

Fixes #15840

datetime.datetime.utcnow() and utcfromtimestamp() are deprecated since Python 3.12 and scheduled for removal. In google-cloud-ndb they are called from the _now() staticmethods of DateTimeProperty, DateProperty and TimeProperty, so every auto_now / auto_now_add put currently emits a DeprecationWarning; the legacy value decoder emits another one for its epoch constant. Running the unit suite on Python 3.14 produced 70 such warnings.

Changes

  • Add a private _utcnow() helper to model.py, next to _getfullargspec, and route the three _now() methods through it.
  • Build the _EPOCH constant in _legacy_db_get_value() as datetime.datetime(1970, 1, 1) instead of utcfromtimestamp(0) (same value).
  • Update the tests that used the deprecated calls; add test__utcnow.

Why the helper strips tzinfo

The recommended replacement, datetime.now(timezone.utc), returns an offset-aware value, but DateTimeProperty._validate() rejects offset-aware values unless the property is configured with tzinfo. A plain substitution would therefore make auto_now raise BadValueError for every property without tzinfo. The helper calls .replace(tzinfo=None) to keep returning the naive-UTC value ndb has always stored and compared — the same approach google-auth takes in _helpers.utcnow().

Verification

  • nox -s unit-equivalent run on Python 3.10 and 3.14: 1835 passed.
  • utcnow / utcfromtimestamp warnings: 70 → 0.
  • ruff format --check and flake8 clean.
  • System tests collect (360); the touched test_insert_datetime_property_with_tz now uses the same instant for both the aware and the naive value.

- Route the `_now()` staticmethods of DateTimeProperty, DateProperty and
  TimeProperty through a private `_utcnow()` helper in model.py, and build
  the epoch constant in `_legacy_db_get_value()` directly instead of via
  `utcfromtimestamp()`
- Both APIs are deprecated since Python 3.12 and scheduled for removal; every
  `auto_now`/`auto_now_add` put currently raises a DeprecationWarning, and the
  legacy value decoder raises another
- The helper strips `tzinfo` after calling `now(timezone.utc)`, because
  `DateTimeProperty._validate()` rejects offset-aware values unless the
  property is configured with `tzinfo`

Fixes googleapis#15840
@skippdot
skippdot requested a review from a team as a code owner August 21, 2026 08:57

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces deprecated datetime.datetime.utcnow() and datetime.datetime.utcfromtimestamp() calls with Python 3.12-compatible alternatives. A new helper function _utcnow() is introduced to return naive UTC datetimes, preserving the expected behavior of ndb which stores and compares naive datetimes. The changes are accompanied by updated unit and system tests. There are no review comments to address, and the implementation looks solid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

utcnow() Deprecation Warning

1 participant