diff --git a/bson/json_util.py b/bson/json_util.py index 925897e94..9186a2c09 100644 --- a/bson/json_util.py +++ b/bson/json_util.py @@ -188,18 +188,23 @@ def object_hook(dct, compile_re=True): micros = int(dtm[20:23]) * 1000 aware = naive.replace(microsecond=micros, tzinfo=utc) offset = dtm[23:] - if not offset: - # No offset, assume UTC. + if not offset or offset == 'Z': + # UTC return aware - elif len(offset) == 5: - # Offset from mongoexport is in format (+|-)HHMM - secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60) + else: + if len(offset) == 5: + # Offset from mongoexport is in format (+|-)HHMM + secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60) + elif ':' in offset and len(offset) == 6: + # RFC-3339 format (+|-)HH:MM + hours, minutes = offset[1:].split(':') + secs = (int(hours) * 3600 + int(minutes) * 60) + else: + # Not RFC-3339 compliant or mongoexport output. + raise ValueError("invalid format for offset") if offset[0] == "-": secs *= -1 return aware - datetime.timedelta(seconds=secs) - else: - # Some other tool created this, or mongoexport changed again? - raise ValueError("invalid format for offset") # mongoexport 2.6 and newer, time before the epoch (SERVER-15275) elif isinstance(dtm, dict): secs = float(dtm["$numberLong"]) / 1000.0 diff --git a/test/test_json_util.py b/test/test_json_util.py index 8b6a7dd94..744ab1940 100644 --- a/test/test_json_util.py +++ b/test/test_json_util.py @@ -85,19 +85,23 @@ class TestJsonUtil(unittest.TestCase): jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+0000"}}' self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) + jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+00:00"}}' + self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) + jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000Z"}}' + self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) # No explicit offset jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000"}}' self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) # Localtime behind UTC jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-0800"}}' self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) + jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-08:00"}}' + self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) # Localtime ahead of UTC jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+0100"}}' self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) - - # Unsupported offset format jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+01:00"}}' - self.assertRaises(ValueError, json_util.loads, jsn) + self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"]) dtm = datetime.datetime(1, 1, 1, 1, 1, 1, 0, utc) jsn = '{"dt": {"$date": -62135593139000}}'