Skip to content

date.fromisoformat() silently ignores the last two characters of a 10-character basic-format string #158500

Open

Description

@fitness-trener

Bug report

Bug description:

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.

CPython versions tested on:

3.11, CPython main branch

Operating systems tested on:

Windows

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    on Sep 30, 2026
  2. rupayon123 commented on Oct 1, 2026

    @rupayon123

    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.

  3. fitness-trener commented on Oct 1, 2026

    @fitness-trener
    Author

    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.)

  4. rupayon123 commented on Oct 1, 2026

    @rupayon123

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions