Serialize dates and times to isoformat (#58157)

This commit is contained in:
Erik Montnemery 2021-10-27 19:51:38 +02:00 committed by GitHub
parent ced89d8f29
commit abb84d9756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 21 deletions

View File

@ -1,5 +1,5 @@
"""Helpers to help with encoding Home Assistant objects in JSON.""" """Helpers to help with encoding Home Assistant objects in JSON."""
from datetime import datetime, timedelta import datetime
import json import json
from typing import Any from typing import Any
@ -12,7 +12,7 @@ class JSONEncoder(json.JSONEncoder):
Hand other objects to the original method. Hand other objects to the original method.
""" """
if isinstance(o, datetime): if isinstance(o, datetime.datetime):
return o.isoformat() return o.isoformat()
if isinstance(o, set): if isinstance(o, set):
return list(o) return list(o)
@ -30,8 +30,12 @@ class ExtendedJSONEncoder(JSONEncoder):
Fall back to repr(o). Fall back to repr(o).
""" """
if isinstance(o, timedelta): if isinstance(o, datetime.timedelta):
return {"__type": str(type(o)), "total_seconds": o.total_seconds()} return {"__type": str(type(o)), "total_seconds": o.total_seconds()}
if isinstance(o, datetime.datetime):
return o.isoformat()
if isinstance(o, (datetime.date, datetime.time)):
return {"__type": str(type(o)), "isoformat": o.isoformat()}
try: try:
return super().default(o) return super().default(o)
except TypeError: except TypeError:

View File

@ -1,5 +1,5 @@
"""Test Home Assistant remote methods and classes.""" """Test Home Assistant remote methods and classes."""
from datetime import timedelta import datetime
import pytest import pytest
@ -8,9 +8,10 @@ from homeassistant.helpers.json import ExtendedJSONEncoder, JSONEncoder
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
def test_json_encoder(hass): @pytest.mark.parametrize("encoder", (JSONEncoder, ExtendedJSONEncoder))
"""Test the JSON Encoder.""" def test_json_encoder(hass, encoder):
ha_json_enc = JSONEncoder() """Test the JSON encoders."""
ha_json_enc = encoder()
state = core.State("test.test", "hello") state = core.State("test.test", "hello")
# Test serializing a datetime # Test serializing a datetime
@ -24,22 +25,21 @@ def test_json_encoder(hass):
# Test serializing an object which implements as_dict # Test serializing an object which implements as_dict
assert ha_json_enc.default(state) == state.as_dict() assert ha_json_enc.default(state) == state.as_dict()
def test_json_encoder_raises(hass):
"""Test the JSON encoder raises on unsupported types."""
ha_json_enc = JSONEncoder()
# Default method raises TypeError if non HA object # Default method raises TypeError if non HA object
with pytest.raises(TypeError): with pytest.raises(TypeError):
ha_json_enc.default(1) ha_json_enc.default(1)
def test_trace_json_encoder(hass): def test_extended_json_encoder(hass):
"""Test the Trace JSON Encoder.""" """Test the extended JSON encoder."""
ha_json_enc = ExtendedJSONEncoder() ha_json_enc = ExtendedJSONEncoder()
state = core.State("test.test", "hello")
# Test serializing a datetime
now = dt_util.utcnow()
assert ha_json_enc.default(now) == now.isoformat()
# Test serializing a timedelta # Test serializing a timedelta
data = timedelta( data = datetime.timedelta(
days=50, days=50,
seconds=27, seconds=27,
microseconds=10, microseconds=10,
@ -53,12 +53,13 @@ def test_trace_json_encoder(hass):
"total_seconds": data.total_seconds(), "total_seconds": data.total_seconds(),
} }
# Test serializing a set() # Test serializing a time
data = {"milk", "beer"} o = datetime.time(7, 20)
assert sorted(ha_json_enc.default(data)) == sorted(data) assert ha_json_enc.default(o) == {"__type": str(type(o)), "isoformat": "07:20:00"}
# Test serializong object which implements as_dict # Test serializing a date
assert ha_json_enc.default(state) == state.as_dict() o = datetime.date(2021, 12, 24)
assert ha_json_enc.default(o) == {"__type": str(type(o)), "isoformat": "2021-12-24"}
# Default method falls back to repr(o) # Default method falls back to repr(o)
o = object() o = object()