diff --git a/oslo_serialization/msgpackutils.py b/oslo_serialization/msgpackutils.py index 570e3a5..ac4f703 100644 --- a/oslo_serialization/msgpackutils.py +++ b/oslo_serialization/msgpackutils.py @@ -19,7 +19,7 @@ import uuid import msgpack from oslo_utils import importutils -from oslo_utils import timeutils +from pytz import timezone import six import six.moves.xmlrpc_client as xmlrpclib @@ -34,14 +34,33 @@ else: def _serialize_datetime(dt): - blob = timeutils.strtime(dt) - if six.PY3: - return blob.encode('ascii') - return blob + dct = { + 'day': dt.day, + 'month': dt.month, + 'year': dt.year, + 'hour': dt.hour, + 'minute': dt.minute, + 'second': dt.second, + 'microsecond': dt.microsecond, + } + if dt.tzinfo: + dct['tz'] = dt.tzinfo.tzname(None) + return dumps(dct) def _deserialize_datetime(blob): - return timeutils.parse_strtime(six.text_type(blob, encoding='ascii')) + dct = loads(blob) + dt = datetime.datetime(day=dct['day'], + month=dct['month'], + year=dct['year'], + hour=dct['hour'], + minute=dct['minute'], + second=dct['second'], + microsecond=dct['microsecond']) + if 'tz' in dct: + tzinfo = timezone(dct['tz']) + dt = tzinfo.localize(dt) + return dt def _serializer(obj): diff --git a/requirements.txt b/requirements.txt index eb6cf00..74ef925 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ msgpack-python>=0.4.0 # library version this can be removed. iso8601>=0.1.9 oslo.utils>=1.2.0 # Apache-2.0 +pytz>=2013.6 diff --git a/tests/test_msgpackutils.py b/tests/test_msgpackutils.py index 00c6c6b..8a9f965 100644 --- a/tests/test_msgpackutils.py +++ b/tests/test_msgpackutils.py @@ -19,6 +19,7 @@ import uuid import netaddr from oslotest import base as test_base +from pytz import timezone import six import six.moves.xmlrpc_client as xmlrpclib import testtools @@ -33,6 +34,9 @@ else: _PY26 = False +_TZ_FMT = '%Y-%m-%d %H:%M:%S %Z%z' + + def _dumps_loads(obj): obj = msgpackutils.dumps(obj) return msgpackutils.loads(obj) @@ -107,7 +111,7 @@ class MsgPackUtilsTestMixin(test_base.BaseTestCase): x = datetime.datetime(1920, 2, 3, 4, 5, 6, 7) self.assertEqual(_dumps_loads(x), x) - def test_DateTime(self): + def test_datetime(self): x = xmlrpclib.DateTime() x.decode("19710203T04:05:06") self.assertEqual(_dumps_loads(x), x) @@ -115,3 +119,31 @@ class MsgPackUtilsTestMixin(test_base.BaseTestCase): def test_ipaddr(self): thing = {'ip_addr': netaddr.IPAddress('1.2.3.4')} self.assertEqual(_dumps_loads(thing), thing) + + def test_datetime_tz_clone(self): + eastern = timezone('US/Eastern') + now = datetime.datetime.now() + e_dt = eastern.localize(now) + e_dt2 = _dumps_loads(e_dt) + self.assertEqual(e_dt, e_dt2) + self.assertEqual(e_dt.strftime(_TZ_FMT), e_dt2.strftime(_TZ_FMT)) + + def test_datetime_tz_different(self): + eastern = timezone('US/Eastern') + pacific = timezone('US/Pacific') + now = datetime.datetime.now() + + e_dt = eastern.localize(now) + p_dt = pacific.localize(now) + + self.assertNotEqual(e_dt, p_dt) + self.assertNotEqual(e_dt.strftime(_TZ_FMT), p_dt.strftime(_TZ_FMT)) + + e_dt2 = _dumps_loads(e_dt) + p_dt2 = _dumps_loads(p_dt) + + self.assertNotEqual(e_dt2, p_dt2) + self.assertNotEqual(e_dt2.strftime(_TZ_FMT), p_dt2.strftime(_TZ_FMT)) + + self.assertEqual(e_dt, e_dt2) + self.assertEqual(p_dt, p_dt2)