turbo_broccoli.custom.datetime

Python datetime objects (de)serialization

See also: https://docs.python.org/3/library/datetime.html

  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()
def from_json(dct: dict, ctx: turbo_broccoli.context.Context) -> Any:
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
def to_json(obj: Any, ctx: turbo_broccoli.context.Context) -> dict:
 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>,
    }