Skip to content

Commit 01866e6

Browse files
🐛 Preserve months when using the Pendulum Duration type (#283)
* Preserve months when using the Pendulum Duration type * format
1 parent 3cf70f5 commit 01866e6

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

pydantic_extra_types/pendulum_dt.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,25 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
199199
Returns:
200200
The validated value or raises a PydanticCustomError.
201201
"""
202-
# if we are passed an existing instance, pass it straight through.
203-
if isinstance(value, (_Duration, timedelta)):
204-
return Duration(seconds=value.total_seconds())
202+
203+
if isinstance(value, _Duration):
204+
return Duration(
205+
years=value.years,
206+
months=value.months,
207+
weeks=value.weeks,
208+
days=value.remaining_days,
209+
hours=value.hours,
210+
minutes=value.minutes,
211+
seconds=value.remaining_seconds,
212+
microseconds=value.microseconds,
213+
)
214+
215+
if isinstance(value, timedelta):
216+
return Duration(
217+
days=value.days,
218+
seconds=value.seconds,
219+
microseconds=value.microseconds,
220+
)
205221

206222
try:
207223
parsed = parse(value, exact=True)

tests/test_pendulum_dt.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,30 @@ def test_pendulum_date_existing_instance(instance):
9292
[
9393
pendulum.duration(days=42, hours=13, minutes=37),
9494
pendulum.duration(days=-42, hours=13, minutes=37),
95+
pendulum.duration(weeks=97),
96+
pendulum.duration(days=463),
97+
pendulum.duration(milliseconds=90122),
98+
pendulum.duration(microseconds=90122),
99+
pendulum.duration(
100+
years=2,
101+
months=3,
102+
weeks=19,
103+
days=1,
104+
hours=25,
105+
seconds=732,
106+
milliseconds=123,
107+
microseconds=1324,
108+
),
95109
timedelta(days=42, hours=13, minutes=37),
96110
timedelta(days=-42, hours=13, minutes=37),
111+
timedelta(
112+
weeks=19,
113+
days=1,
114+
hours=25,
115+
seconds=732,
116+
milliseconds=123,
117+
microseconds=1324,
118+
),
97119
],
98120
)
99121
def test_duration_timedelta__existing_instance(instance):
@@ -227,7 +249,11 @@ def test_pendulum_dt_from_str_unix_timestamp_is_utc(dt):
227249

228250
@pytest.mark.parametrize(
229251
'd',
230-
[pendulum.now().date().isoformat(), pendulum.now().to_w3c_string(), pendulum.now().to_iso8601_string()],
252+
[
253+
pendulum.now().date().isoformat(),
254+
pendulum.now().to_w3c_string(),
255+
pendulum.now().to_iso8601_string(),
256+
],
231257
)
232258
def test_pendulum_date_from_serialized(d):
233259
"""Verifies that building an instance from serialized, well-formed strings decode properly."""
@@ -308,7 +334,10 @@ def test_pendulum_dt_non_strict_malformed(dt):
308334
DtModelNotStrict(dt=dt)
309335

310336

311-
@pytest.mark.parametrize('invalid_value', [None, 'malformed', pendulum.today().to_iso8601_string()[:5], 'P10Y10M10D'])
337+
@pytest.mark.parametrize(
338+
'invalid_value',
339+
[None, 'malformed', pendulum.today().to_iso8601_string()[:5], 'P10Y10M10D'],
340+
)
312341
def test_pendulum_date_malformed(invalid_value):
313342
"""Verifies that the instance fails to validate if malformed date are passed."""
314343
with pytest.raises(ValidationError):
@@ -317,7 +346,14 @@ def test_pendulum_date_malformed(invalid_value):
317346

318347
@pytest.mark.parametrize(
319348
'delta_t',
320-
[None, 'malformed', pendulum.today().to_iso8601_string()[:5], 42, '12m', '2021-01-01T12:00:00'],
349+
[
350+
None,
351+
'malformed',
352+
pendulum.today().to_iso8601_string()[:5],
353+
42,
354+
'12m',
355+
'2021-01-01T12:00:00',
356+
],
321357
)
322358
def test_pendulum_duration_malformed(delta_t):
323359
"""Verifies that the instance fails to validate if malformed durations are passed."""
@@ -344,3 +380,9 @@ def test_date_type_adapter(input_type: type, value, is_instance: type):
344380
assert type(validated) is input_type
345381
assert isinstance(validated, input_type)
346382
assert isinstance(validated, is_instance)
383+
384+
385+
def test_pendulum_duration_months_are_preserved():
386+
m = DurationModel(delta_t=pendulum.Duration(months=1))
387+
388+
assert m.delta_t.months == 1

0 commit comments

Comments
 (0)