Skip to content

Commit bba49fd

Browse files
committed
PYTHON-864 - Support RFC-3339 offset format for $date.
1 parent 902dbe7 commit bba49fd

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

bson/json_util.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,23 @@ def object_hook(dct):
148148
aware = datetime.datetime.strptime(
149149
dtm[:23], "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=utc)
150150
offset = dtm[23:]
151-
if not offset:
152-
# No offset, assume UTC.
151+
if not offset or offset == 'Z':
152+
# UTC
153153
return aware
154-
elif len(offset) == 5:
155-
# Offset from mongoexport is in format (+|-)HHMM
156-
secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60)
154+
else:
155+
if len(offset) == 5:
156+
# Offset from mongoexport is in format (+|-)HHMM
157+
secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60)
158+
elif ':' in offset and len(offset) == 6:
159+
# RFC-3339 format (+|-)HH:MM
160+
hours, minutes = offset[1:].split(':')
161+
secs = (int(hours) * 3600 + int(minutes) * 60)
162+
else:
163+
# Not RFC-3339 compliant or mongoexport output.
164+
raise ValueError("invalid format for offset")
157165
if offset[0] == "-":
158166
secs *= -1
159167
return aware - datetime.timedelta(seconds=secs)
160-
else:
161-
# Some other tool created this, or mongoexport changed again?
162-
raise ValueError("invalid format for offset")
163168
# mongoexport 2.6 and newer, time before the epoch (SERVER-15275)
164169
elif isinstance(dtm, collections.Mapping):
165170
secs = float(dtm["$numberLong"]) / 1000.0

test/test_json_util.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,23 @@ def test_datetime(self):
6969

7070
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+0000"}}'
7171
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
72+
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000+00:00"}}'
73+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
74+
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000Z"}}'
75+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
7276
# No explicit offset
7377
jsn = '{"dt": { "$date" : "1970-01-01T00:00:00.000"}}'
7478
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
7579
# Localtime behind UTC
7680
jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-0800"}}'
7781
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
82+
jsn = '{"dt": { "$date" : "1969-12-31T16:00:00.000-08:00"}}'
83+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
7884
# Localtime ahead of UTC
7985
jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+0100"}}'
8086
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
81-
82-
# Unsupported offset format
8387
jsn = '{"dt": { "$date" : "1970-01-01T01:00:00.000+01:00"}}'
84-
self.assertRaises(ValueError, json_util.loads, jsn)
85-
88+
self.assertEqual(EPOCH_AWARE, json_util.loads(jsn)["dt"])
8689

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

0 commit comments

Comments
 (0)