Skip to content

datetime.fromisoformat(): Omitted colon in timezone suffix raises ValueError #86537

Description

@BengtLers
mannequin
BPO 42371
Nosy @abalkin, @pganssle

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2020-11-16.15:00:17.385>
labels = ['type-feature', 'library', '3.10']
title = 'datetime.fromisoformat(): Omitted colon in timezone suffix raises ValueError'
updated_at = <Date 2020-11-16.17:16:24.723>
user = 'https://bugs.python.org/BengtLers'

bugs.python.org fields:

activity = <Date 2020-11-16.17:16:24.723>
actor = 'p-ganssle'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2020-11-16.15:00:17.385>
creator = 'Bengt.L\xc3\xbcers'
dependencies = []
files = []
hgrepos = []
issue_num = 42371
keywords = []
message_count = 2.0
messages = ['381102', '381127']
nosy_count = 3.0
nosy_names = ['belopolsky', 'Bengt.L\xc3\xbcers', 'p-ganssle']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue42371'
versions = ['Python 3.10']

Activity

  1. BengtLers commented on Nov 16, 2020

    BengtLersmannequin
    MannequinAuthor

    I am trying to parse ISO8601-formatted datetime strings with timezones.

    This works fine when there is a colon separating the hour and minute digits:

    >> import datetime
    >> datetime.datetime.fromisoformat('2020-11-16T11:00:00+00:00')
    >> datetime.datetime(2020, 11, 16, 11, 0, tzinfo=datetime.timezone.utc)

    However this fails when there is no colon between the hour and the minute digits:

    >>> import datetime
    >>> datetime.datetime.fromisoformat('2020-11-16T11:00:00+0000')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: Invalid isoformat string: '2020-11-16T11:00:00+0000'

    This behavior is unexpected, as the ISO8601 standard allows omitting the colon in the string and defining the timezone as "<time>±hhmm
    ":

    https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC

    As a workaround, I normalized the timezone suffixes before parsing:

    >> if iso8601_string.endswith('+0000'):
    >> return iso8601_string[:-len('+0000')] + '+00:00'
    >> if iso8601_string.endswith('+00'):
    >> return iso8601_string[:-len('+00')] + '+00:00'
    >> if iso8601_string.endswith('-0000'):
    >> return iso8601_string[:-len('-0000')] + '+00:00'
    >> if iso8601_string.endswith('-00'):
    >> return iso8601_string[:-len('-00')] + '+00:00'

    This only works for the UTC timezone. I would be nice to have a more general solution which can handle any timezone.

    I tested this with CPython 3.8. .fromisoformat() was added in 3.7, so earlier versions should not be affected by this:

    https://docs.python.org/3/library/datetime.html#datetime.date.fromisoformat

  2. added
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    on Nov 16, 2020
  3. changed the title [-]Missing colon in timezone suffix raises ValueError[/-] [+]datetime.fromisoformat(): Missing colon in timezone suffix raises ValueError[/+] on Nov 16, 2020
  4. changed the title [-]datetime.fromisoformat(): Missing colon in timezone suffix raises ValueError[/-] [+]datetime.fromisoformat(): Omitted colon in timezone suffix raises ValueError[/+] on Nov 16, 2020
  5. pganssle commented on Nov 16, 2020

    @pganssle
    Member

    This is the expected behavior of .fromisoformat(). A similar issue is https://bugs.python.org/issue35829, which asks for the "Z" suffix to be supported.

    There is a note about this in the documentation: https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat

    "Caution This does not support parsing arbitrary ISO 8601 strings - it is only intended as the inverse operation of datetime.isoformat(). A more full-featured ISO 8601 parser, dateutil.parser.isoparse is available in the third-party package dateutil."

    At some point we will work out the kinks in offering as full an ISO 8601 datetime parser as possible, but the ISO 8601 datetime spec is very complicated and includes many optional features. We deliberately chose to keep the scope of .fromisoformat() minimal at first, whereas dateutil.parser.isoparse attempts to be a full-featured ISO8601 parser.

    Changing the version affected to 3.10, since this is a feature request.

  6. added
    type-featureA feature request or enhancement
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Nov 16, 2020
  7. transferred this issue fromon Apr 10, 2022
  8. Paebbels commented on Feb 23, 2024

    @Paebbels

    Omitting the colon is not allowed by the standard! The wikipedia article is not very precise as it shows individual aspects of a date and time, but no compiled rule. Please also not that many ISO 8601 regular expressions are not strict enough to fully match the EBNF rules of the standard.

    This wrong behavior was now introduced in Python 3.11, 3.12 and 3.13 and allows invalid datetime strings to be parsed as ISO 8601.
    See #115783.

    When reading the EBNF rules of ISO 8601, either all elements of a datetime are in basic format (in short: no separators) or all elements are in extended format (in short: with separators). A mix of basic format and extended format is not allowed.

  9. added and removed on Mar 1, 2025
  10. StanFromIreland commented on Mar 10, 2025

    @StanFromIreland
    Member

    This has been implemented accidentally at some point in time. This issue should be closed. Whether this should be there or not is for #115783

  11. encukou commented on Mar 11, 2025

    @encukou
    Member

    This is a duplicate (or, subset) of #80010, where Paul added a parser for all but the weirdest variants of ISO 8601.

    Also note that fromisoformat does not necessarily validate that the input strictly conforms to the standard.

  12. pganssle commented on Mar 11, 2025

    @pganssle
    Member

    Also note that fromisoformat does not necessarily validate that the input strictly conforms to the standard.

    That was the original intention, IIRC, this may have just been a mistake. The only exception I recall for fromisoformat() is that because isoformat allows outputting an arbitrary single-character separator, fromisoformat allows parsing dates with an arbitrary separator. The intention was also to be generous with the parts of the spec that are allowed to be modified by mutual agreement (whatever that means), e.g. number of digits in the fractional portion.

    I am not sure it is worth it to try to walk back support for "almost" ISO8601 formats like mixed extended and basic formats.

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 dirstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions