Skip to content

Commit cdd564f

Browse files
authored
πŸ› fix: serialize Pendulum zero Duration as valid ISO 8601 'P0D' (#320)
* πŸ› fix: serialize Pendulum zero Duration as valid ISO 8601 'P0D' Previously output 'P' which is not parsable. * πŸ› fix: serialize Pendulum zero Duration as valid ISO 8601 'P0D' * ✨test: add tests for Pendulum zero-duration serialization and parsing
1 parent d8a4459 commit cdd564f

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

β€Žpydantic_extra_types/pendulum_dt.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ def to_iso8601_string(self) -> str:
244244
if self.total_seconds() < 0:
245245
iso_duration = '-' + iso_duration
246246

247+
if iso_duration == 'P':
248+
iso_duration = 'P0D'
249+
247250
return iso_duration
248251

249252
@classmethod

β€Žtests/test_pendulum_dt.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,35 @@ def test_pendulum_duration_months_are_preserved():
414414
m = DurationModel(delta_t=pendulum.Duration(months=1))
415415

416416
assert m.delta_t.months == 1
417+
418+
419+
@pytest.mark.parametrize(
420+
'zero_duration',
421+
[
422+
Duration(),
423+
Duration(years=0, months=0, days=0, hours=0, minutes=0, seconds=0),
424+
Duration(0),
425+
pendulum.duration(),
426+
],
427+
)
428+
def test_zero_duration_serialization_and_validation(zero_duration):
429+
"""Zero durations should serialize as 'P0D' and round-trip without error."""
430+
model = DurationModel(delta_t=zero_duration)
431+
json_dump = model.model_dump_json()
432+
assert json_dump == '{"delta_t":"P0D"}'
433+
loaded = DurationModel.model_validate_json(json_dump)
434+
assert loaded.delta_t == zero_duration
435+
assert isinstance(loaded.delta_t, Duration)
436+
437+
438+
def test_zero_duration_from_string():
439+
"""'P0D' string should be accepted and produce a zero Duration."""
440+
model = DurationModel(delta_t='P0D')
441+
assert model.delta_t == Duration()
442+
assert isinstance(model.delta_t, Duration)
443+
444+
445+
def test_invalid_zero_duration_string():
446+
"""'P' is not a valid ISO 8601 duration and should raise a validation error."""
447+
with pytest.raises(ValidationError):
448+
DurationModel(delta_t='P')

0 commit comments

Comments
Β (0)