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