turbo_broccoli.custom.datetime
Python datetime objects (de)serialization
1""" 2Python datetime objects (de)serialization 3 4See also: 5 https://docs.python.org/3/library/datetime.html 6""" 7 8from datetime import datetime, time, timedelta 9from typing import Any, Callable, Tuple 10 11from ..context import Context 12from ..exceptions import DeserializationError, TypeNotSupported 13 14 15def _datetime_to_json(obj: datetime, ctx: Context) -> dict: 16 return { 17 "__type__": "datetime.datetime", 18 "__version__": 1, 19 "datetime": obj.isoformat(), 20 } 21 22 23def _time_to_json(obj: time, ctx: Context) -> dict: 24 return { 25 "__type__": "datetime.time", 26 "__version__": 1, 27 "time": obj.isoformat(), 28 } 29 30 31def _timedelta_to_json(obj: timedelta, ctx: Context) -> dict: 32 return { 33 "__type__": "datetime.timedelta", 34 "__version__": 1, 35 "days": obj.days, 36 "microseconds": obj.microseconds, 37 "seconds": obj.seconds, 38 } 39 40 41def _json_to_datetime(dct: dict, ctx: Context) -> datetime: 42 decoders = { 43 1: _json_to_datetime_v1, 44 } 45 return decoders[dct["__version__"]](dct, ctx) 46 47 48def _json_to_datetime_v1(dct: dict, ctx: Context) -> datetime: 49 return datetime.fromisoformat(dct["datetime"]) 50 51 52def _json_to_time(dct: dict, ctx: Context) -> time: 53 decoders = { 54 1: _json_to_time_v1, 55 } 56 return decoders[dct["__version__"]](dct, ctx) 57 58 59def _json_to_time_v1(dct: dict, ctx: Context) -> time: 60 return time.fromisoformat(dct["time"]) 61 62 63def _json_to_timedelta(dct: dict, ctx: Context) -> timedelta: 64 decoders = { 65 1: _json_to_timedelta_v1, 66 } 67 return decoders[dct["__version__"]](dct, ctx) 68 69 70def _json_to_timedelta_v1(dct: dict, ctx: Context) -> timedelta: 71 return timedelta( 72 days=dct["days"], 73 microseconds=dct["microseconds"], 74 seconds=dct["seconds"], 75 ) 76 77 78def from_json(dct: dict, ctx: Context) -> Any: 79 decoders = { 80 "datetime.datetime": _json_to_datetime, 81 "datetime.time": _json_to_time, 82 "datetime.timedelta": _json_to_timedelta, 83 } 84 try: 85 type_name = dct["__type__"] 86 return decoders[type_name](dct, ctx) 87 except KeyError as exc: 88 raise DeserializationError() from exc 89 90 91def to_json(obj: Any, ctx: Context) -> dict: 92 """ 93 Serializes a XXX into JSON by cases. See the README for the precise list of 94 supported types. The return dict has the following structure: 95 96 - `datetime.datetime`: 97 98 ```py 99 { 100 "__type__": "datetime.datetime", 101 "__version__": 1, 102 "datetime": <ISO format>, 103 } 104 ``` 105 106 - `datetime.time`: 107 108 ```py 109 { 110 "__type__": "datetime.time", 111 "__version__": 1, 112 "time": <ISO format>, 113 } 114 ``` 115 116 - `datetime.timedelta`: 117 118 ```py 119 { 120 "__type__": "datetime.timedelta", 121 "__version__": 1, 122 "days": <int>, 123 "microseconds": <int>, 124 "seconds": <int>, 125 } 126 ``` 127 """ 128 encoders: list[Tuple[type, Callable[[Any, Context], dict]]] = [ 129 (datetime, _datetime_to_json), 130 (time, _time_to_json), 131 (timedelta, _timedelta_to_json), 132 ] 133 for t, f in encoders: 134 if isinstance(obj, t): 135 return f(obj, ctx) 136 raise TypeNotSupported()
79def from_json(dct: dict, ctx: Context) -> Any: 80 decoders = { 81 "datetime.datetime": _json_to_datetime, 82 "datetime.time": _json_to_time, 83 "datetime.timedelta": _json_to_timedelta, 84 } 85 try: 86 type_name = dct["__type__"] 87 return decoders[type_name](dct, ctx) 88 except KeyError as exc: 89 raise DeserializationError() from exc
92def to_json(obj: Any, ctx: Context) -> dict: 93 """ 94 Serializes a XXX into JSON by cases. See the README for the precise list of 95 supported types. The return dict has the following structure: 96 97 - `datetime.datetime`: 98 99 ```py 100 { 101 "__type__": "datetime.datetime", 102 "__version__": 1, 103 "datetime": <ISO format>, 104 } 105 ``` 106 107 - `datetime.time`: 108 109 ```py 110 { 111 "__type__": "datetime.time", 112 "__version__": 1, 113 "time": <ISO format>, 114 } 115 ``` 116 117 - `datetime.timedelta`: 118 119 ```py 120 { 121 "__type__": "datetime.timedelta", 122 "__version__": 1, 123 "days": <int>, 124 "microseconds": <int>, 125 "seconds": <int>, 126 } 127 ``` 128 """ 129 encoders: list[Tuple[type, Callable[[Any, Context], dict]]] = [ 130 (datetime, _datetime_to_json), 131 (time, _time_to_json), 132 (timedelta, _timedelta_to_json), 133 ] 134 for t, f in encoders: 135 if isinstance(obj, t): 136 return f(obj, ctx) 137 raise TypeNotSupported()
Serializes a XXX into JSON by cases. See the README for the precise list of supported types. The return dict has the following structure:
datetime.datetime
:{ "__type__": "datetime.datetime", "__version__": 1, "datetime": <ISO format>, }
datetime.time
:{ "__type__": "datetime.time", "__version__": 1, "time": <ISO format>, }
datetime.timedelta
:{ "__type__": "datetime.timedelta", "__version__": 1, "days": <int>, "microseconds": <int>, "seconds": <int>, }