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 turbo_broccoli.context import Context 12from turbo_broccoli.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 78# pylint: disable=missing-function-docstring 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 90 91 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()
80def from_json(dct: dict, ctx: Context) -> Any: 81 decoders = { 82 "datetime.datetime": _json_to_datetime, 83 "datetime.time": _json_to_time, 84 "datetime.timedelta": _json_to_timedelta, 85 } 86 try: 87 type_name = dct["__type__"] 88 return decoders[type_name](dct, ctx) 89 except KeyError as exc: 90 raise DeserializationError() from exc
93def to_json(obj: Any, ctx: Context) -> dict: 94 """ 95 Serializes a XXX into JSON by cases. See the README for the precise list of 96 supported types. The return dict has the following structure: 97 98 - `datetime.datetime`: 99 100 ```py 101 { 102 "__type__": "datetime.datetime", 103 "__version__": 1, 104 "datetime": <ISO format>, 105 } 106 ``` 107 108 - `datetime.time`: 109 110 ```py 111 { 112 "__type__": "datetime.time", 113 "__version__": 1, 114 "time": <ISO format>, 115 } 116 ``` 117 118 - `datetime.timedelta`: 119 120 ```py 121 { 122 "__type__": "datetime.timedelta", 123 "__version__": 1, 124 "days": <int>, 125 "microseconds": <int>, 126 "seconds": <int>, 127 } 128 ``` 129 """ 130 encoders: list[Tuple[type, Callable[[Any, Context], dict]]] = [ 131 (datetime, _datetime_to_json), 132 (time, _time_to_json), 133 (timedelta, _timedelta_to_json), 134 ] 135 for t, f in encoders: 136 if isinstance(obj, t): 137 return f(obj, ctx) 138 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>, }