Skip to content

Commit 4942a4a

Browse files
committed
Epoch - unix timestamp
using type float, format: date-time to serialize datetime.datetime
1 parent f7875f0 commit 4942a4a

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

pydantic_extra_types/epoch.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import datetime
2+
from typing import Any, Callable
3+
4+
from pydantic import GetJsonSchemaHandler
5+
from pydantic.json_schema import JsonSchemaValue
6+
from pydantic_core import CoreSchema, core_schema
7+
8+
EPOCH = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
9+
10+
11+
class Epoch(datetime.datetime):
12+
@classmethod
13+
def __get_pydantic_json_schema__(
14+
cls, core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler
15+
) -> JsonSchemaValue:
16+
field_schema: dict[str, Any] = {}
17+
field_schema.update(type='number', format='date-time')
18+
return field_schema
19+
20+
@classmethod
21+
def __get_pydantic_core_schema__(
22+
cls, source: type[Any], handler: Callable[[Any], CoreSchema]
23+
) -> core_schema.CoreSchema:
24+
def f(value, serializer):
25+
return serializer(value.timestamp())
26+
return core_schema.with_info_after_validator_function(
27+
cls._validate, core_schema.float_schema(),
28+
serialization=core_schema.wrap_serializer_function_ser_schema(f, return_schema=core_schema.float_schema())
29+
)
30+
31+
@classmethod
32+
def _validate(cls, __input_value: Any, _: Any) -> "Epoch":
33+
return EPOCH + datetime.timedelta(seconds=__input_value)
34+
35+

tests/test_epoch.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import datetime
2+
3+
import pytest
4+
5+
from pydantic_extra_types.epoch import Epoch
6+
7+
@pytest.mark.parametrize('type_',[(int,),(float,)], ids=["integer", "float"])
8+
def test_type(type_):
9+
from pydantic import BaseModel
10+
11+
class A(BaseModel):
12+
epoch: Epoch
13+
14+
now = datetime.datetime.now(tz=datetime.timezone.utc)
15+
ts = type_(now.timestamp())
16+
a = A.model_validate({"epoch":ts})
17+
v = a.model_dump()
18+
assert v["epoch"] == ts
19+
20+
b = A.model_construct(epoch=now)
21+
22+
v = b.model_dump()
23+
assert v["epoch"] == ts
24+
25+
c = A.model_validate(dict(epoch=ts))
26+
v = c.model_dump()
27+
assert v["epoch"] == ts
28+
29+
30+
def test_schema():
31+
from pydantic import BaseModel
32+
class A(BaseModel):
33+
dt: Epoch
34+
35+
v = A.model_json_schema()
36+
assert (dt:=v["properties"]["dt"])["type"] == "number" and dt["format"] == "date-time"
37+

0 commit comments

Comments
 (0)