diff --git a/src/pendulum/parsing/iso8601.py b/src/pendulum/parsing/iso8601.py index c65d249e..7c9145a8 100644 --- a/src/pendulum/parsing/iso8601.py +++ b/src/pendulum/parsing/iso8601.py @@ -296,7 +296,7 @@ def _parse_iso8601_duration(text: str, **options: str) -> Duration | None: if "." in _weeks: _weeks, portion = _weeks.split(".") weeks = int(_weeks) - _days = int(portion) / 10 * 7 + _days = int(portion) / 10 ** len(portion) * 7 days, hours = int(_days // 1), int(_days % 1 * HOURS_PER_DAY) else: weeks = int(_weeks) @@ -344,7 +344,7 @@ def _parse_iso8601_duration(text: str, **options: str) -> Duration | None: _days, _hours = _days.split(".") days = int(_days) - hours = int(_hours) / 10 * HOURS_PER_DAY + hours = int(_hours) / 10 ** len(_hours) * HOURS_PER_DAY else: days = int(_days) @@ -374,7 +374,7 @@ def _parse_iso8601_duration(text: str, **options: str) -> Duration | None: _hours, _mins = _hours.split(".") hours += int(_hours) - minutes += int(_mins) / 10 * MINUTES_PER_HOUR + minutes += int(_mins) / 10 ** len(_mins) * MINUTES_PER_HOUR else: hours += int(_hours) @@ -389,7 +389,7 @@ def _parse_iso8601_duration(text: str, **options: str) -> Duration | None: _minutes, _secs = _minutes.split(".") minutes += int(_minutes) - seconds += int(_secs) / 10 * SECONDS_PER_MINUTE + seconds += int(_secs) / 10 ** len(_secs) * SECONDS_PER_MINUTE else: minutes += int(_minutes) diff --git a/tests/parsing/test_parsing_duration.py b/tests/parsing/test_parsing_duration.py index d6a0b73d..77b205de 100644 --- a/tests/parsing/test_parsing_duration.py +++ b/tests/parsing/test_parsing_duration.py @@ -304,3 +304,21 @@ def test_parse_interval_invalid(): def test_parse_duration_fraction_only_allowed_on_last_component(): with pytest.raises(ParserError): parse("P2Y3M4DT5.5H6M7S") + + +@pytest.mark.parametrize( + "text, seconds", + [ + ("P1.5D", 129600), # one fractional digit, already correct + ("P1.25D", 108000), + ("PT1.25H", 4500), + ("PT1.05M", 63), + ("P1.25W", 756000), + ], +) +def test_parse_duration_multi_digit_fraction(text, seconds): + # Imports the pure-Python parser directly: `parse` uses the Rust extension + # unless PENDULUM_EXTENSIONS=0, so going through it would not exercise this. + from pendulum.parsing.iso8601 import parse_iso8601 + + assert parse_iso8601(text).total_seconds() == seconds