Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions packages/google-cloud-ndb/google/cloud/ndb/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,17 @@ class Person(Model):
_getfullargspec = inspect.getfullargspec


def _utcnow():
"""Return the current UTC time as a naive :class:`~datetime.datetime`.

``datetime.datetime.utcnow()`` is deprecated since Python 3.12 and
scheduled for removal. Its replacement, ``datetime.datetime.now(timezone.utc)``,
returns an offset-aware value, but ``ndb`` stores and compares naive
datetimes presumed to be UTC, so the offset is stripped again here.
"""
return datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)


class KindError(exceptions.BadValueError):
"""Raised when an implementation for a kind can't be found.

Expand Down Expand Up @@ -2092,7 +2103,7 @@ def _legacy_db_get_value(v, p):
# A custom 'meaning' for compressed properties.
_MEANING_URI_COMPRESSED = "ZLIB"
# The Epoch (a zero POSIX timestamp).
_EPOCH = datetime.datetime.utcfromtimestamp(0)
_EPOCH = datetime.datetime(1970, 1, 1)
# This is awkward but there seems to be no faster way to inspect
# what union member is present. datastore_types.FromPropertyPb(),
# the undisputed authority, has the same series of if-elif blocks.
Expand Down Expand Up @@ -3933,7 +3944,7 @@ def _now():

Subclasses will override this to return different forms of "now".
"""
return datetime.datetime.utcnow()
return _utcnow()

def _prepare_for_put(self, entity):
"""Sets the current timestamp when "auto" is set.
Expand Down Expand Up @@ -4055,7 +4066,7 @@ def _from_base_type(self, value):
@staticmethod
def _now():
"""datetime.datetime: Return current date."""
return datetime.datetime.utcnow().date()
return _utcnow().date()


class TimeProperty(DateTimeProperty):
Expand Down Expand Up @@ -4124,7 +4135,7 @@ def _from_base_type(self, value):
@staticmethod
def _now():
"""datetime.datetime: Return current time."""
return datetime.datetime.utcnow().time()
return _utcnow().time()


class StructuredProperty(Property):
Expand Down
2 changes: 1 addition & 1 deletion packages/google-cloud-ndb/tests/system/test_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ class SomeKind(ndb.Model):
now = datetime.datetime.now(pytz.utc)
entity = SomeKind(
alarm1=now,
alarm2=datetime.datetime.utcnow(), # naive
alarm2=now.replace(tzinfo=None), # same instant, naive
)
key = entity.put()
dispose_of(key._key)
Expand Down
19 changes: 15 additions & 4 deletions packages/google-cloud-ndb/tests/unit/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,17 @@ def test__fix_up():
assert attr._fix_up(model.Model, "birthdate") is None


def test__utcnow():
before = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
value = model._utcnow()
after = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)

# ndb stores naive datetimes presumed to be UTC, so the helper must not
# leak the tzinfo that datetime.now(timezone.utc) attaches.
assert value.tzinfo is None
assert before <= value <= after


class Test_BaseValue:
@staticmethod
def test_constructor():
Expand Down Expand Up @@ -2974,7 +2985,7 @@ def test_constructor_defaults():

@staticmethod
def test_constructor_explicit():
now = datetime.datetime.utcnow()
now = model._utcnow()
prop = model.DateTimeProperty(
name="dt_val",
auto_now=True,
Expand Down Expand Up @@ -3014,7 +3025,7 @@ def test_constructor_repeated():
@staticmethod
def test__validate():
prop = model.DateTimeProperty(name="dt_val")
value = datetime.datetime.utcnow()
value = model._utcnow()
assert prop._validate(value) is None

@staticmethod
Expand Down Expand Up @@ -3150,7 +3161,7 @@ class TestDateProperty:
@staticmethod
def test__validate():
prop = model.DateProperty(name="d_val")
value = datetime.datetime.utcnow().date()
value = model._utcnow().date()
assert prop._validate(value) is None

@staticmethod
Expand Down Expand Up @@ -3186,7 +3197,7 @@ class TestTimeProperty:
@staticmethod
def test__validate():
prop = model.TimeProperty(name="t_val")
value = datetime.datetime.utcnow().time()
value = model._utcnow().time()
assert prop._validate(value) is None

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion packages/google-cloud-ndb/tests/unit/test_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
DEFAULTS = {
"bytes": 4,
"count": 2,
"timestamp": datetime.datetime.utcfromtimestamp(40),
"timestamp": datetime.datetime(1970, 1, 1, 0, 0, 40),
}


Expand Down
Loading