Skip to content

Commit d4a75e6

Browse files
committed
Accept ISO 8601 fractional seconds with more than 9 digits
The pure-Python ISO 8601 parser capped the subsecond group at 9 digits (\d{1,9}), so parse() raised a ParserError on timestamps with 10 or more fractional-second digits, even though the Rust parser and datetime.fromisoformat accept them and truncate to microsecond resolution. Widen the group to \d+; the existing [:6] truncation already converts any length down to microseconds, so the result is unchanged for inputs that already parsed. Fixes #935
1 parent 1d9e31a commit d4a75e6

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

src/pendulum/parsing/iso8601.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
# Subsecond part (optional)
5050
" (?P<subsecondsection>"
5151
" (?:[.,])" # Subsecond separator (optional)
52-
r" (?P<subsecond>\d{1,9})" # Subsecond
52+
r" (?P<subsecond>\d+)" # Subsecond
5353
" )?"
5454
# Timezone offset
5555
" (?P<tz>"

tests/parsing/test_parse_iso8601.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import pytest
88

99
from pendulum.parsing import parse_iso8601
10+
from pendulum.parsing.iso8601 import parse_iso8601 as parse_iso8601_python
1011

1112

1213
try:
@@ -214,3 +215,26 @@ def test_parse_iso8601_duration_invalid():
214215
# Must include at least one element
215216
with pytest.raises(ValueError):
216217
parse_iso8601("P")
218+
219+
220+
@pytest.mark.parametrize(
221+
["text", "expected"],
222+
[
223+
# 10 and more fractional-second digits (issue #935)
224+
(
225+
"2001-01-01T12:34:56.1234567890",
226+
datetime(2001, 1, 1, 12, 34, 56, 123456),
227+
),
228+
(
229+
"2001-01-01T12:34:56.123456789012",
230+
datetime(2001, 1, 1, 12, 34, 56, 123456),
231+
),
232+
("12:34:56.1234567890", time(12, 34, 56, 123456)),
233+
],
234+
)
235+
def test_parse_iso8601_subsecond_more_than_nine_digits(text, expected):
236+
# The pure-Python ISO 8601 parser must accept fractional seconds with more
237+
# than 9 digits and truncate to microsecond resolution, matching the Rust
238+
# parser and datetime.fromisoformat, instead of failing to parse.
239+
# https://github.com/python-pendulum/pendulum/issues/935
240+
assert parse_iso8601_python(text) == expected

0 commit comments

Comments
 (0)