diff --git a/gcloud/datastore/helpers.py b/gcloud/datastore/helpers.py index ccef721e97b4d..7e5309778f13a 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()) * 10**6) + val.microsecond elif isinstance(val, Key): name, value = 'key', val.to_protobuf() elif isinstance(val, bool): diff --git a/gcloud/datastore/test_helpers.py b/gcloud/datastore/test_helpers.py index 262ebe511a9a3..3e1653bade5fd 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()) * 10**6 + now.microsecond)), (Key(), Key().to_protobuf()), )