Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.

Commit ad42606

Browse files
author
Chris Rossi
authored
fix: fix bug when setting naive datetime on DateTimeProperty with timezone (#534)
Fixes #517
1 parent 49f9e48 commit ad42606

3 files changed

Lines changed: 69 additions & 0 deletions

File tree

google/cloud/ndb/model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3747,6 +3747,8 @@ def _from_base_type(self, value):
37473747
value = datetime.datetime.fromtimestamp(seconds, pytz.utc)
37483748

37493749
if self._tzinfo is not None:
3750+
if value.tzinfo is None:
3751+
value = value.replace(tzinfo=pytz.utc)
37503752
return value.astimezone(self._tzinfo)
37513753

37523754
elif value.tzinfo is not None:

tests/system/test_crud.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import datetime
1919
import os
2020
import pickle
21+
import pytz
2122
import random
2223
import threading
2324
import zlib
@@ -40,6 +41,11 @@
4041
USE_REDIS_CACHE = bool(os.environ.get("REDIS_CACHE_URL"))
4142

4243

44+
def _assert_contemporaneous(timestamp1, timestamp2, delta_margin=2):
45+
delta_margin = datetime.timedelta(seconds=delta_margin)
46+
assert delta_margin > abs(timestamp1 - timestamp2)
47+
48+
4349
@pytest.mark.usefixtures("client_context")
4450
def test_retrieve_entity(ds_entity):
4551
entity_id = test_utils.system.unique_resource_id()
@@ -1043,6 +1049,59 @@ class SomeKind(ndb.Model):
10431049
assert isinstance(retrieved.updated_at, datetime.datetime)
10441050

10451051

1052+
@pytest.mark.usefixtures("client_context")
1053+
def test_insert_autonow_property_with_tz(dispose_of):
1054+
"""Regression test for #517
1055+
1056+
https://github.com/googleapis/python-ndb/issues/517
1057+
"""
1058+
1059+
class SomeKind(ndb.Model):
1060+
created_at = ndb.DateTimeProperty(auto_now_add=True, tzinfo=pytz.utc)
1061+
updated_at = ndb.DateTimeProperty(auto_now=True, tzinfo=pytz.utc)
1062+
1063+
now = datetime.datetime.now(pytz.utc)
1064+
entity = SomeKind()
1065+
key = entity.put()
1066+
dispose_of(key._key)
1067+
1068+
_assert_contemporaneous(entity.created_at, now)
1069+
_assert_contemporaneous(entity.updated_at, now)
1070+
1071+
retrieved = key.get()
1072+
1073+
_assert_contemporaneous(retrieved.created_at, now)
1074+
_assert_contemporaneous(retrieved.updated_at, now)
1075+
1076+
1077+
@pytest.mark.usefixtures("client_context")
1078+
def test_insert_datetime_property_with_tz(dispose_of):
1079+
"""Regression test for #517
1080+
1081+
https://github.com/googleapis/python-ndb/issues/517
1082+
"""
1083+
1084+
class SomeKind(ndb.Model):
1085+
alarm1 = ndb.DateTimeProperty(tzinfo=pytz.utc)
1086+
alarm2 = ndb.DateTimeProperty(tzinfo=pytz.utc)
1087+
1088+
now = datetime.datetime.now(pytz.utc)
1089+
entity = SomeKind(
1090+
alarm1=now,
1091+
alarm2=datetime.datetime.utcnow(), # naive
1092+
)
1093+
key = entity.put()
1094+
dispose_of(key._key)
1095+
1096+
_assert_contemporaneous(entity.alarm1, now)
1097+
_assert_contemporaneous(entity.alarm2, now)
1098+
1099+
retrieved = key.get()
1100+
1101+
_assert_contemporaneous(retrieved.alarm1, now)
1102+
_assert_contemporaneous(retrieved.alarm2, now)
1103+
1104+
10461105
@pytest.mark.usefixtures("client_context")
10471106
def test_insert_nested_autonow_property(dispose_of):
10481107
class OtherKind(ndb.Model):

tests/unit/test_model.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2784,6 +2784,14 @@ def test__from_base_type_convert_timezone():
27842784
2010, 5, 11, 20, tzinfo=timezone(-4)
27852785
)
27862786

2787+
@staticmethod
2788+
def test__from_base_type_naive_with_timezone():
2789+
prop = model.DateTimeProperty(name="dt_val", tzinfo=timezone(-4))
2790+
value = datetime.datetime(2010, 5, 12)
2791+
assert prop._from_base_type(value) == datetime.datetime(
2792+
2010, 5, 11, 20, tzinfo=timezone(-4)
2793+
)
2794+
27872795
@staticmethod
27882796
def test__from_base_type_int():
27892797
prop = model.DateTimeProperty(name="dt_val")

0 commit comments

Comments
 (0)