You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
date.fromisoformat() silently ignores the last two characters of a 10-character basic-format string #158500
date.fromisoformat() accepts a 10-character string in basic format and silently drops its last two characters:
>>> from datetime import date, datetime
>>> date.fromisoformat('2020010112') # e.g. a YYYYMMDDHH stamp
datetime.date(2020, 1, 1)
>>> date.fromisoformat('2020W011xx')
datetime.date(2019, 12, 30)
>>> datetime.fromisoformat('2020010112') # the datetime parser rejects it
ValueError: Invalid isoformat string: '2020010112'
date.fromisoformat admits inputs of length 7, 8 or 10. Both parse_isoformat_date() in Modules/_datetimemodule.c and _parse_isoformat_date() in Lib/_pydatetime.py read fixed-width fields from the start of the string, and neither checks that the whole string was consumed. A 10-character string without - at index 4 is therefore parsed as the 8-character basic date YYYYMMDD (or YYYYWwwD), and the trailing characters are ignored.
Such a string is not an ISO 8601 date, and it is not one of the documented exceptions. Because the result is a plausible date, a truncated or mistyped input (such as a 10-digit YYYYMMDDHH) goes unnoticed.
Checked on:
3.11.15 with the C accelerator: the output above;
Lib/_pydatetime.py from main (7eada7c), run under 3.11.15: same results for both strings;
Modules/_datetimemodule.c on main: read, not built. The code path is unchanged.
Suggested fix: after the last field, require that the whole string has been consumed (p - dtstr == len in C, len(dtstr) == pos in Python). I have a draft patch with tests for both implementations and can open a PR if this is accepted.
Found by differential testing fromisoformat against an independent ISO 8601 implementation. I found no existing report; the nearest is gh-152204, which covers other pure-Python-only inputs.
I saw your note that you had a draft patch. I reproduced the issue and opened #158557 with full-input checks in both the C and pure-Python parsers, plus shared regression tests. If you're actively preparing a PR, please let us know so we can coordinate and avoid duplicating work; I'm happy to defer to the more complete approach.
Thanks for picking this up! I'm not preparing a PR. Your change matches my draft almost line for line, and you have a built and tested CPython, which I didn't. Please go ahead.
One suggestion: add '20200101\u00e9' to test_fromisoformat_fails. It is 9 characters but 10 bytes of UTF-8, so it reaches the C parser's 10-byte branch. Your length check rejects it, but on 3.11.15 the C parser returned date(2020, 1, 1) for it, so it is worth pinning. (_pydatetime already rejects it at the ASCII check.)
Thanks for checking this against 3.11.15. I added 20200101é to the date-only test_fromisoformat_fails cases so it covers the 9-character/10-byte C-parser path, alongside the existing pure-Python implementation. The change is in 57801f4 on PR #158557. The focused test_fromisoformat_fails cases pass for both implementations, and the full test_datetime suite passes (1,166 tests, 33 skipped). I’ll keep an eye on the exact-head CI before treating the PR as fully validated.
Activity
rupayon123 commentedon Oct 1, 2026
I saw your note that you had a draft patch. I reproduced the issue and opened #158557 with full-input checks in both the C and pure-Python parsers, plus shared regression tests. If you're actively preparing a PR, please let us know so we can coordinate and avoid duplicating work; I'm happy to defer to the more complete approach.
fitness-trener commentedon Oct 1, 2026
Thanks for picking this up! I'm not preparing a PR. Your change matches my draft almost line for line, and you have a built and tested CPython, which I didn't. Please go ahead.
One suggestion: add
'20200101\u00e9'totest_fromisoformat_fails. It is 9 characters but 10 bytes of UTF-8, so it reaches the C parser's 10-byte branch. Your length check rejects it, but on 3.11.15 the C parser returneddate(2020, 1, 1)for it, so it is worth pinning. (_pydatetimealready rejects it at the ASCII check.)rupayon123 commentedon Oct 1, 2026
Thanks for checking this against 3.11.15. I added
20200101éto the date-onlytest_fromisoformat_failscases so it covers the 9-character/10-byte C-parser path, alongside the existing pure-Python implementation. The change is in 57801f4 on PR #158557. The focusedtest_fromisoformat_failscases pass for both implementations, and the fulltest_datetimesuite passes (1,166 tests, 33 skipped). I’ll keep an eye on the exact-head CI before treating the PR as fully validated.