Skip to content

Commit 2598869

Browse files
committed
PYTHON-864 - Support RFC-3339 offset format for $date.
1 parent 43347f6 commit 2598869

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

bson/json_util.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,23 @@ def object_hook(dct, compile_re=True):
188188
micros = int(dtm[20:23]) * 1000
189189
aware = naive.replace(microsecond=micros, tzinfo=utc)
190190
offset = dtm[23:]
191-
if not offset:
192-
# No offset, assume UTC.
191+
if not offset or offset == 'Z':
192+
# UTC
193193
return aware
194-
elif len(offset) == 5:
195-
# Offset from mongoexport is in format (+|-)HHMM
196-
secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60)
194+
else:
195+
if len(offset) == 5:
196+
# Offset from mongoexport is in format (+|-)HHMM
197+
secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60)
198+
elif ':' in offset and len(offset) == 6:
199+
# RFC-3339 format (+|-)HH:MM
200+
hours, minutes = offset[1:].split(':')
201+
secs = (int(hours) * 3600 + int(minutes) * 60)
202+
else:
203+
# Not RFC-3339 compliant or mongoexport output.
204+
raise ValueError("invalid format for offset")
197205
if offset[0] == "-":
198206
secs *= -1
199207
return aware - datetime.timedelta(seconds=secs)
200-
else:
201-
# Some other tool created this, or mongoexport changed again?
202-
raise ValueError("invalid format for offset")
203208
# mongoexport 2.6 and newer, time before the epoch (SERVER-15275)
204209
elif isinstance(dtm, dict):
205210
secs = float(dtm["$numberLong"]) / 1000.0

test/test_json_util.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,23 @@ def test_datetime(self):
8585

8686
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+0000"}}'
8787
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
88+
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+00:00"}}'
89+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
90+
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000Z"}}'
91+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
8892
# No explicit offset
8993
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000"}}'
9094
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
9195
# Localtime behind UTC
9296
jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-0800"}}'
9397
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
98+
jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-08:00"}}'
99+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
94100
# Localtime ahead of UTC
95101
jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+0100"}}'
96102
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
97-
98-
# Unsupported offset format
99103
jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+01:00"}}'
100-
self.assertRaises(ValueError, json_util.loads, jsn)
104+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
101105

102106
dtm = datetime.datetime(1, 1, 1, 1, 1, 1, 0, utc)
103107
jsn = '{"dt": {"$date": -62135593139000}}'

0 commit comments

Comments
 (0)