Skip to content

Commit 498980f

Browse files
author
pepe-rtmlab
committed
add native datetime to pendulum_dt.py
1 parent 2ef94e7 commit 498980f

File tree

2 files changed

+69
-14
lines changed

2 files changed

+69
-14
lines changed

pydantic_extra_types/pendulum_dt.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Native Pendulum DateTime object implementation. This is a copy of the Pendulum DateTime object, but with a Pydantic
33
CoreSchema implementation. This allows Pydantic to validate the DateTime object.
44
"""
5+
import pendulum
56

67
try:
78
from pendulum import Date as _Date
@@ -13,6 +14,7 @@
1314
'The `pendulum_dt` module requires "pendulum" to be installed. You can install it with "pip install pendulum".'
1415
)
1516
from typing import Any, List, Type
17+
from datetime import datetime, date, timedelta
1618

1719
from pydantic import GetCoreSchemaHandler
1820
from pydantic_core import PydanticCustomError, core_schema
@@ -68,6 +70,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
6870
if isinstance(value, _DateTime):
6971
return handler(value)
7072

73+
if isinstance(value, datetime):
74+
return handler(DateTime.instance(value))
75+
7176
# otherwise, parse it.
7277
try:
7378
data = parse(value)
@@ -126,6 +131,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
126131
if isinstance(value, _Date):
127132
return handler(value)
128133

134+
if isinstance(value, date):
135+
return handler(pendulum.instance(value))
136+
129137
# otherwise, parse it.
130138
try:
131139
data = parse(value)
@@ -184,6 +192,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
184192
if isinstance(value, _Duration):
185193
return handler(value)
186194

195+
if isinstance(value, timedelta):
196+
return handler(_Duration(seconds=value.total_seconds()))
197+
187198
# otherwise, parse it.
188199
try:
189200
data = parse(value)

tests/test_pendulum_dt.py

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pendulum
22
import pytest
33
from pydantic import BaseModel, ValidationError
4+
from datetime import datetime, date, timedelta, UTC
45

56
from pydantic_extra_types.pendulum_dt import Date, DateTime, Duration
67

@@ -17,33 +18,76 @@ class DurationModel(BaseModel):
1718
delta_t: Duration
1819

1920

20-
def test_pendulum_dt_existing_instance():
21+
@pytest.mark.parametrize(
22+
'instance',
23+
[
24+
pendulum.now(),
25+
datetime.now(),
26+
datetime.now(UTC),
27+
],
28+
)
29+
def test_existing_instance(instance):
2130
"""
2231
Verifies that constructing a model with an existing pendulum dt doesn't throw.
2332
"""
24-
now = pendulum.now()
25-
model = DtModel(dt=now)
26-
assert model.dt == now
33+
model = DtModel(dt=instance)
34+
if isinstance(instance, datetime):
35+
assert model.dt == pendulum.instance(instance)
36+
if instance.tzinfo is None and isinstance(instance, datetime):
37+
instance = model.dt.replace(tzinfo=UTC) # pendulum defaults to UTC
38+
dt = model.dt
39+
else:
40+
assert model.dt == instance
41+
dt = model.dt
42+
43+
assert dt.day == instance.day
44+
assert dt.month == instance.month
45+
assert dt.year == instance.year
46+
assert dt.hour == instance.hour
47+
assert dt.minute == instance.minute
48+
assert dt.second == instance.second
49+
assert dt.microsecond == instance.microsecond
50+
if dt.tzinfo != instance.tzinfo:
51+
assert dt.tzinfo.utcoffset(dt) == instance.tzinfo.utcoffset(instance)
2752

2853

29-
def test_pendulum_date_existing_instance():
54+
@pytest.mark.parametrize(
55+
'instance',
56+
[
57+
pendulum.today(),
58+
date.today(),
59+
],
60+
)
61+
def test_pendulum_date_existing_instance(instance):
3062
"""
3163
Verifies that constructing a model with an existing pendulum date doesn't throw.
3264
"""
33-
today = pendulum.today().date()
34-
model = DateModel(d=today)
35-
assert model.d == today
36-
65+
model = DateModel(d=instance)
66+
if isinstance(instance, datetime):
67+
assert model.d == pendulum.instance(instance).date()
68+
else:
69+
assert model.d == instance
70+
d = model.d
71+
assert d.day == instance.day
72+
assert d.month == instance.month
73+
assert d.year == instance.year
3774

38-
def test_pendulum_duration_existing_instance():
75+
@pytest.mark.parametrize(
76+
'instance',
77+
[
78+
pendulum.duration(days=42, hours=13, minutes=37),
79+
pendulum.duration(days=-42, hours=13, minutes=37),
80+
timedelta(days=42, hours=13, minutes=37),
81+
timedelta(days=-42, hours=13, minutes=37),
82+
],
83+
)
84+
def test_duration_timedelta__existing_instance(instance):
3985
"""
4086
Verifies that constructing a model with an existing pendulum duration doesn't throw.
4187
"""
42-
delta_t = pendulum.duration(days=42, hours=13, minutes=37)
43-
model = DurationModel(delta_t=delta_t)
44-
45-
assert model.delta_t.total_seconds() == delta_t.total_seconds()
88+
model = DurationModel(delta_t=instance)
4689

90+
assert model.delta_t.total_seconds() == instance.total_seconds()
4791

4892
@pytest.mark.parametrize(
4993
'dt',

0 commit comments

Comments
 (0)