Skip to content

Commit 1303f8c

Browse files
authored
gh-80010: Expand fromisoformat to include most of ISO-8601 (#92177)
This expands `fromisoformat` to cover most of the common uses of ISO 8601. We may expand the scope more in the future.
1 parent ada8b6d commit 1303f8c

File tree

6 files changed

+778
-178
lines changed

6 files changed

+778
-178
lines changed

Doc/library/datetime.rst

+48-35
Original file line numberDiff line numberDiff line change
@@ -526,18 +526,20 @@ Other constructors, all class methods:
526526

527527
.. classmethod:: date.fromisoformat(date_string)
528528

529-
Return a :class:`date` corresponding to a *date_string* given in the format
530-
``YYYY-MM-DD``::
529+
Return a :class:`date` corresponding to a *date_string* given in any valid
530+
ISO 8601 format, except ordinal dates (e.g. ``YYYY-DDD``)::
531531

532532
>>> from datetime import date
533533
>>> date.fromisoformat('2019-12-04')
534534
datetime.date(2019, 12, 4)
535-
536-
This is the inverse of :meth:`date.isoformat`. It only supports the format
537-
``YYYY-MM-DD``.
535+
>>> date.fromisoformat('20191204')
536+
datetime.date(2019, 12, 4)
537+
>>> date.fromisoformat('2021-W01-1')
538+
datetime.date(2021, 1, 4)
538539

539540
.. versionadded:: 3.7
540-
541+
.. versionchanged:: 3.11
542+
Previously, this method only supported the format ``YYYY-MM-DD``.
541543

542544
.. classmethod:: date.fromisocalendar(year, week, day)
543545

@@ -710,8 +712,6 @@ Instance methods:
710712
>>> date(2002, 12, 4).isoformat()
711713
'2002-12-04'
712714

713-
This is the inverse of :meth:`date.fromisoformat`.
714-
715715
.. method:: date.__str__()
716716

717717
For a date *d*, ``str(d)`` is equivalent to ``d.isoformat()``.
@@ -994,31 +994,29 @@ Other constructors, all class methods:
994994

995995
.. classmethod:: datetime.fromisoformat(date_string)
996996

997-
Return a :class:`.datetime` corresponding to a *date_string* in one of the
998-
formats emitted by :meth:`date.isoformat` and :meth:`datetime.isoformat`.
999-
1000-
Specifically, this function supports strings in the format:
997+
Return a :class:`.datetime` corresponding to a *date_string* in any valid
998+
ISO 8601 format, with the following exceptions:
1001999

1002-
.. code-block:: none
1003-
1004-
YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]
1005-
1006-
where ``*`` can match any single character.
1007-
1008-
.. caution::
1009-
1010-
This does *not* support parsing arbitrary ISO 8601 strings - it is only intended
1011-
as the inverse operation of :meth:`datetime.isoformat`. A more full-featured
1012-
ISO 8601 parser, ``dateutil.parser.isoparse`` is available in the third-party package
1013-
`dateutil <https://dateutil.readthedocs.io/en/stable/parser.html#dateutil.parser.isoparse>`__.
1000+
1. Time zone offsets may have fractional seconds.
1001+
2. The `T` separator may be replaced by any single unicode character.
1002+
3. Ordinal dates are not currently supported.
1003+
4. Fractional hours and minutes are not supported.
10141004

10151005
Examples::
10161006

10171007
>>> from datetime import datetime
10181008
>>> datetime.fromisoformat('2011-11-04')
10191009
datetime.datetime(2011, 11, 4, 0, 0)
1010+
>>> datetime.fromisoformat('20111104')
1011+
datetime.datetime(2011, 11, 4, 0, 0)
10201012
>>> datetime.fromisoformat('2011-11-04T00:05:23')
10211013
datetime.datetime(2011, 11, 4, 0, 5, 23)
1014+
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')
1015+
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
1016+
>>> datetime.fromisoformat('20111104T000523')
1017+
datetime.datetime(2011, 11, 4, 0, 5, 23)
1018+
>>> datetime.fromisoformat('2011-W01-2T00:05:23.283')
1019+
datetime.datetime(2011, 1, 4, 0, 5, 23, 283000)
10221020
>>> datetime.fromisoformat('2011-11-04 00:05:23.283')
10231021
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000)
10241022
>>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00')
@@ -1028,6 +1026,10 @@ Other constructors, all class methods:
10281026
tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
10291027

10301028
.. versionadded:: 3.7
1029+
.. versionchanged:: 3.11
1030+
Previously, this method only supported formats that could be emitted by
1031+
:meth:`date.isoformat()` or :meth:`datetime.isoformat()`.
1032+
10311033

10321034
.. classmethod:: datetime.fromisocalendar(year, week, day)
10331035

@@ -1763,30 +1765,41 @@ Other constructor:
17631765

17641766
.. classmethod:: time.fromisoformat(time_string)
17651767

1766-
Return a :class:`.time` corresponding to a *time_string* in one of the
1767-
formats emitted by :meth:`time.isoformat`. Specifically, this function supports
1768-
strings in the format:
1769-
1770-
.. code-block:: none
1771-
1772-
HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
1773-
1774-
.. caution::
1768+
Return a :class:`.time` corresponding to a *time_string* in any valid
1769+
ISO 8601 format, with the following exceptions:
17751770

1776-
This does *not* support parsing arbitrary ISO 8601 strings. It is only
1777-
intended as the inverse operation of :meth:`time.isoformat`.
1771+
1. Time zone offsets may have fractional seconds.
1772+
2. The leading `T`, normally required in cases where there may be ambiguity between
1773+
a date and a time, is not required.
1774+
3. Fractional seconds may have any number of digits (anything beyond 6 will
1775+
be truncated).
1776+
4. Fractional hours and minutes are not supported.
17781777

17791778
Examples::
17801779

17811780
>>> from datetime import time
17821781
>>> time.fromisoformat('04:23:01')
17831782
datetime.time(4, 23, 1)
1783+
>>> time.fromisoformat('T04:23:01')
1784+
datetime.time(4, 23, 1)
1785+
>>> time.fromisoformat('T042301')
1786+
datetime.time(4, 23, 1)
17841787
>>> time.fromisoformat('04:23:01.000384')
17851788
datetime.time(4, 23, 1, 384)
1789+
>>> time.fromisoformat('04:23:01,000')
1790+
datetime.time(4, 23, 1, 384)
17861791
>>> time.fromisoformat('04:23:01+04:00')
17871792
datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
1793+
>>> time.fromisoformat('04:23:01Z')
1794+
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)
1795+
>>> time.fromisoformat('04:23:01+00:00')
1796+
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)
1797+
17881798

17891799
.. versionadded:: 3.7
1800+
.. versionchanged:: 3.11
1801+
Previously, this method only supported formats that could be emitted by
1802+
:meth:`time.isoformat()`.
17901803

17911804

17921805
Instance methods:

Doc/whatsnew/3.11.rst

+8
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,14 @@ asyncio
425425
existing stream-based connections to TLS. (Contributed by Ian Good in
426426
:issue:`34975`.)
427427

428+
datetime
429+
--------
430+
431+
* :meth:`datetime.date.fromisoformat`, :meth:`datetime.time.fromisoformat` and
432+
:meth:`datetime.datetime.fromisoformat` can now be used to parse most ISO 8601
433+
formats (barring only those that support fractional hours and minutes).
434+
(Contributed by Paul Ganssle in :gh:`80010`.)
435+
428436
fractions
429437
---------
430438

0 commit comments

Comments
 (0)