diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index ccef721e97b4..7ec16a67f868 100644 --- a/gcloud/datastore/helpers.py +++ b/gcloud/datastore/helpers.py @@ -1,6 +1,6 @@ """Helper methods for dealing with Cloud Datastore's Protobuf API.""" +import calendar from datetime import datetime -import time import pytz @@ -37,7 +37,15 @@ def get_protobuf_attribute_and_value(val): """ if isinstance(val, datetime): - name, value = 'timestamp_microseconds', time.mktime(val.timetuple()) + name = 'timestamp_microseconds' + # If the datetime is naive (no timezone), consider that it was + # intended to be UTC and replace the tzinfo to that effect. + if not val.tzinfo: + val = val.replace(tzinfo=pytz.utc) + # Regardless of what timezone is on the value, convert it to UTC. + val = val.astimezone(pytz.utc) + # Convert the datetime to a microsecond timestamp. + value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond elif isinstance(val, Key): name, value = 'key', val.to_protobuf() elif isinstance(val, bool): @@ -69,8 +77,9 @@ def get_value_from_protobuf(pb): """ if pb.value.HasField('timestamp_microseconds_value'): - timestamp = pb.value.timestamp_microseconds_value / 1e6 - return datetime.fromtimestamp(timestamp).replace(tzinfo=pytz.utc) + microseconds = pb.value.timestamp_microseconds_value + return (datetime.utcfromtimestamp(0) + + datetime.timedelta(microseconds=microseconds)) elif pb.value.HasField('key_value'): return Key.from_protobuf(pb.value.key_value) diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 262ebe511a9a..d40cd4e86833 100644 --- a/gcloud/datastore/test_helpers.py +++ b/gcloud/datastore/test_helpers.py @@ -1,3 +1,4 @@ +import calendar from datetime import datetime import time @@ -28,7 +29,7 @@ def test_get_protobuf_attribute(self): test_value, expected_name, actual_name)) def test_get_protobuf_value(self): - now = datetime.now() + now = datetime.utcnow() mapping = ( (str('string'), 'string'), @@ -37,7 +38,7 @@ def test_get_protobuf_value(self): (long(), int()), (float(), float()), (bool(), bool()), - (now, time.mktime(now.timetuple())), + (now, long(calendar.timegm(now.timetuple()) * 1e6 + now.microsecond)), (Key(), Key().to_protobuf()), )