Skip to content

Commit

Permalink
[Core] Follow RFC 3339 datetime formatting for AzureJSONEncoder (#20346)
Browse files Browse the repository at this point in the history
  • Loading branch information
mccoyp authored Aug 31, 2021
1 parent 94225f2 commit 6821987
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
1 change: 1 addition & 0 deletions sdk/core/azure-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features Added

- `azure.core.serialization.AzureJSONEncoder` (introduced in 1.17.0) serializes `datetime.datetime` objects in ISO 8601 format, conforming to RFC 3339's specification. #20190
- We now use `azure.core.serialization.AzureJSONEncoder` to serialize `json` input to `azure.core.rest.HttpRequest`.

### Breaking Changes in the Provisional `azure.core.rest` package
Expand Down
7 changes: 5 additions & 2 deletions sdk/core/azure-core/azure/core/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,11 @@ def default(self, o): # pylint: disable=too-many-return-statements
if hasattr(o, "year") and hasattr(o, "hour"):
# astimezone() fails for naive times in Python 2.7, so make make sure o is aware (tzinfo is set)
if not o.tzinfo:
return o.replace(tzinfo=TZ_UTC).isoformat()
return o.astimezone(TZ_UTC).isoformat()
iso_formatted = o.replace(tzinfo=TZ_UTC).isoformat()
else:
iso_formatted = o.astimezone(TZ_UTC).isoformat()
# Replace the trailing "+00:00" UTC offset with "Z" (RFC 3339: https://www.ietf.org/rfc/rfc3339.txt)
return iso_formatted.replace("+00:00", "Z")
# Next try datetime.date or datetime.time
return o.isoformat()
except AttributeError:
Expand Down
28 changes: 14 additions & 14 deletions sdk/core/azure-core/tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test_dictionary_datetime(json_dumps_with_encoder):
expected = {
"timedelta": "P1DT00H00M00S",
"date": "2021-05-12",
"datetime": '2012-02-24T00:53:52.780000+00:00',
"datetime": '2012-02-24T00:53:52.780000Z',
'time': '11:12:13',
}
assert json.loads(json_dumps_with_encoder(test_obj)) == expected
Expand All @@ -167,7 +167,7 @@ def __init__(self):
expected_dict = {
"timedelta": "P1DT00H00M00S",
"date": "2021-05-12",
"datetime": '2012-02-24T00:53:52.780000+00:00',
"datetime": '2012-02-24T00:53:52.780000Z',
'time': '11:12:13',
}
assert json.loads(json_dumps_with_encoder(expected.to_dict())) == expected_dict
Expand Down Expand Up @@ -205,10 +205,10 @@ def __init__(self):
expected_dict = {
"_attributes": {
"enabled": True,
"not_before": "2012-02-24T00:53:52.780000+00:00",
"expires": "2032-02-24T00:53:52.780000+00:00",
"created": "2020-02-24T00:53:52.780000+00:00",
"updated": "2021-02-24T00:53:52.780000+00:00",
"not_before": "2012-02-24T00:53:52.780000Z",
"expires": "2032-02-24T00:53:52.780000Z",
"created": "2020-02-24T00:53:52.780000Z",
"updated": "2021-02-24T00:53:52.780000Z",
},
"_id": "id",
"_vault_id": {
Expand All @@ -229,39 +229,39 @@ def test_serialize_datetime(json_dumps_with_encoder):
date_obj = datetime.strptime('2015-01-01T00:00:00', "%Y-%m-%dT%H:%M:%S")
date_str = json_dumps_with_encoder(date_obj)

assert date_str == '"2015-01-01T00:00:00+00:00"'
assert date_str == '"2015-01-01T00:00:00Z"'

date_obj = datetime.strptime('1999-12-31T23:59:59', "%Y-%m-%dT%H:%M:%S").replace(tzinfo=NegativeUtcOffset())
date_str = json_dumps_with_encoder(date_obj)

assert date_str == '"2000-01-01T11:59:59+00:00"'
assert date_str == '"2000-01-01T11:59:59Z"'

date_obj = datetime.strptime("2015-06-01T16:10:08.0121", "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=PositiveUtcOffset())
date_str = json_dumps_with_encoder(date_obj)

assert date_str == '"2015-06-01T04:10:08.012100+00:00"'
assert date_str == '"2015-06-01T04:10:08.012100Z"'

date_obj = datetime.min
date_str = json_dumps_with_encoder(date_obj)
assert date_str == '"0001-01-01T00:00:00+00:00"'
assert date_str == '"0001-01-01T00:00:00Z"'

date_obj = datetime.max
date_str = json_dumps_with_encoder(date_obj)
assert date_str == '"9999-12-31T23:59:59.999999+00:00"'
assert date_str == '"9999-12-31T23:59:59.999999Z"'

date_obj = datetime.strptime('2012-02-24T00:53:52.000001Z', "%Y-%m-%dT%H:%M:%S.%fZ")
date_str = json_dumps_with_encoder(date_obj)
assert date_str == '"2012-02-24T00:53:52.000001+00:00"'
assert date_str == '"2012-02-24T00:53:52.000001Z"'

date_obj = datetime.strptime('2012-02-24T00:53:52.780Z', "%Y-%m-%dT%H:%M:%S.%fZ")
date_str = json_dumps_with_encoder(date_obj)
assert date_str == '"2012-02-24T00:53:52.780000+00:00"'
assert date_str == '"2012-02-24T00:53:52.780000Z"'

def test_serialize_datetime_subclass(json_dumps_with_encoder):

date_obj = DatetimeSubclass.strptime('2012-02-24T00:53:52.780Z', "%Y-%m-%dT%H:%M:%S.%fZ")
date_str = json_dumps_with_encoder(date_obj)
assert date_str == '"2012-02-24T00:53:52.780000+00:00"'
assert date_str == '"2012-02-24T00:53:52.780000Z"'

def test_serialize_time(json_dumps_with_encoder):

Expand Down

0 comments on commit 6821987

Please sign in to comment.