isoparse function from python-dateutil

The python-dateutil package has dateutil.parser.isoparse to parse not only RFC 3339 datetime strings like the one in the question, but also other ISO 8601 date and time strings that don't comply with RFC 3339 (such as ones with no UTC offset, or ones that represent only a date).

>>> import dateutil.parser
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)

The python-dateutil package also has dateutil.parser.parse. Compared with isoparse, it is presumably less strict, but both of them are quite forgiving and will attempt to interpret the string that you pass in. If you want to eliminate the possibility of any misreads, you need to use something stricter than either of these functions.

Comparison with Python 3.7+’s built-in datetime.datetime.fromisoformat

dateutil.parser.isoparse is a full ISO-8601 format parser, but in Python ≤ 3.10 fromisoformat is deliberately not. In Python 3.11, fromisoformat supports almost all strings in valid ISO 8601. See fromisoformat's docs for this cautionary caveat. (See this answer).

Answer from Flimm on Stack Overflow
🌐
Python documentation
docs.python.org › 3 › library › datetime.html
datetime — Basic date and time types
If format does not contain microseconds or timezone information, this is equivalent to: ... ValueError is raised if the date_string and format cannot be parsed by time.strptime() or if it returns a value which is not a time tuple. See also strftime() and strptime() behavior and time.fromisoformat().
Top answer
1 of 16
700

isoparse function from python-dateutil

The python-dateutil package has dateutil.parser.isoparse to parse not only RFC 3339 datetime strings like the one in the question, but also other ISO 8601 date and time strings that don't comply with RFC 3339 (such as ones with no UTC offset, or ones that represent only a date).

>>> import dateutil.parser
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.isoparse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.isoparse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)

The python-dateutil package also has dateutil.parser.parse. Compared with isoparse, it is presumably less strict, but both of them are quite forgiving and will attempt to interpret the string that you pass in. If you want to eliminate the possibility of any misreads, you need to use something stricter than either of these functions.

Comparison with Python 3.7+’s built-in datetime.datetime.fromisoformat

dateutil.parser.isoparse is a full ISO-8601 format parser, but in Python ≤ 3.10 fromisoformat is deliberately not. In Python 3.11, fromisoformat supports almost all strings in valid ISO 8601. See fromisoformat's docs for this cautionary caveat. (See this answer).

2 of 16
504

Since Python 3.11, the standard library’s datetime.datetime.fromisoformat supports most valid ISO 8601 input (and some non-valid input, see docs). In earlier versions it only parses a specific subset, see the cautionary note at the end of the docs. If you are using Python 3.10 or earlier on strings that don't fall into that subset (like in the question), see other answers for functions from outside the standard library.

The current docs (so exceptions listed are still valid for Python 3.13):

classmethod datetime.fromisoformat(date_string):

Return a datetime corresponding to a date_string in any valid ISO 8601 format, with the following exceptions:

  1. Time zone offsets may have fractional seconds.
  2. The T separator may be replaced by any single unicode character.
  3. Fractional hours and minutes are not supported.
  4. Reduced precision dates are not currently supported (YYYY-MM, YYYY).
  5. Extended date representations are not currently supported (±YYYYYY-MM-DD).
  6. Ordinal dates are not currently supported (YYYY-OOO).

Examples:

>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('20111104')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('2011-11-04T00:05:23')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('20111104T000523')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-W01-2T00:05:23.283')
datetime.datetime(2011, 1, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('2011-11-04T00:05:23+04:00')   
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))

New in version 3.7.

Changed in version 3.11: Previously, this method only supported formats that could be emitted by date.isoformat() or datetime.isoformat().

If you only need dates, and not datetimes, you can use datetime.date.fromisoformat:

>>> from datetime import date
>>> date.fromisoformat("2024-01-31")
datetime.date(2024, 1, 31)
Discussions

Parse "Z" timezone suffix in datetime - Ideas - Discussions on Python.org
Problem Statement The function ... datetime.datetime(2019, 8, 28, 14, 34, 25, 518993, tzinfo=datetime.timezone.utc) The timezone offset in my example is +00:00, i.e. UTC. The ISO-8601 standard (for which fromisoformat() is presumably named) allows “Z” to be used instead of ... More on discuss.python.org
🌐 discuss.python.org
10
August 28, 2019
Python UTC datetime object's ISO format doesn't include Z (Zulu or Zero offset) - Stack Overflow
Python datetimes are a little clunky. Use arrow. > str(arrow.utcnow()) '2014-05-17T01:18:47.944126+00:00' Arrow has essentially the same api as datetime, but with timezones and some extra niceties that should be in the main library. More on stackoverflow.com
🌐 stackoverflow.com
PSA: As of Python 3.11, `datetime.fromisoformat` supports most ISO 8601 formats (notably the "Z" suffix)
Fucking finally. More on reddit.com
🌐 r/Python
34
290
August 28, 2023
datetime: Expand scope of fromisoformat to include all of ISO 8601.
BPO 35829 Nosy @brettcannon, @abalkin, @jwilk, @agronholm, @dlenski, @rdb, @ammaraskar, @mehaase, @pganssle, @hongweipeng, @godlygeek Note: these values reflect the state of the issue at the time i... More on github.com
🌐 github.com
17
January 25, 2019
Top answer
1 of 7
163

To get the current time in UTC in Python 3.2+:

>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2015-01-27T05:57:31.399861+00:00'

To get local time in Python 3.3+:

>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).astimezone().isoformat()
'2015-01-27T06:59:17.125448+01:00'

Explanation: datetime.now(timezone.utc) produces a timezone aware datetime object in UTC time. astimezone() then changes the timezone of the datetime object, to the system's locale timezone if called with no arguments. Timezone aware datetime objects then produce the correct ISO format automatically.

2 of 7
42

You need to make your datetime objects timezone aware. from the datetime docs:

There are two kinds of date and time objects: “naive” and “aware”. This distinction refers to whether the object has any notion of time zone, daylight saving time, or other kind of algorithmic or political time adjustment. Whether a naive datetime object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it’s up to the program whether a particular number represents metres, miles, or mass. Naive datetime objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.

When you have an aware datetime object, you can use isoformat() and get the output you need.

To make your datetime objects aware, you'll need to subclass tzinfo, like the second example in here, or simpler - use a package that does it for you, like pytz or python-dateutil

Using pytz, this would look like:

import datetime, pytz
datetime.datetime.now(timezone.utc).isoformat()

You can also control the output format, if you use strftime with the '%z' format directive like

datetime.datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.%f%z')
🌐
Python.org
discuss.python.org › ideas
Parse "Z" timezone suffix in datetime - Ideas - Discussions on Python.org
August 28, 2019 - This is already opened as BPO 35829 but I wanted to ask about it over here for discussion. Problem Statement The function datetime.fromisoformat() parses a datetime in ISO-8601, format: >>> datetime.fromisoformat('2019-08-28T14:34:25.518993+00:00') datetime.datetime(2019, 8, 28, 14, 34, 25, 518993, tzinfo=datetime.timezone.utc) The timezone offset in my example is +00:00, i.e. UTC.
🌐
Note.nkmk.me
note.nkmk.me › home › python
Convert Between Isoformat String and datetime in Python | note.nkmk.me
August 22, 2023 - You can convert an isoformat string to a datetime object using fromisoformat().
🌐
Joetsoi
joetsoi.github.io › fromisoformat-django-json-encoder-utc-datetimes
Avoid fromisoformat when parsing UTC date times serialized by DjangoJSONEncoder
Well it turns out that Python's fromisoformat currently implements a subset of ISO 8601 and doesn't parse the "Z", as detailed in Issue 35829: datetime: parse "Z" timezone suffix in fromisoformat() - Python tracker and Issue 15873: datetime: add ability to parse RFC 3339 dates and times - Python tracker specifically this comment:
🌐
Statology
statology.org › home › how to work with date and time in iso format in python
How to Work with Date and Time in ISO Format in Python
August 16, 2024 - Python’s datetime module can handle these as well: from datetime import datetime import pytz # Create a timezone-aware datetime tz = pytz.timezone('America/New_York') dt_with_tz = tz.localize(datetime(2024, 7, 30, 14, 30)) # Convert to ISO format iso_with_tz = dt_with_tz.isoformat() print(f"ISO string with timezone: {iso_with_tz}") print(type(iso_with_tz)) # Parse ISO string with timezone parsed_dt = datetime.fromisoformat(iso_with_tz) print(f"Parsed datetime with timezone: {parsed_dt}") print(type(parsed_dt)) Output: ISO string with timezone: 2024-07-30T14:30:00-04:00 <class 'str'> Parsed datetime with timezone: 2024-07-30 14:30:00-04:00 <class 'datetime.datetime'> This example demonstrates the conversion between timezone-aware datetime objects and ISO formatted strings.
🌐
GeeksforGeeks
geeksforgeeks.org › python › fromisoformat-function-of-datetime-date-class-in-python
fromisoformat() method - GeeksforGeeks
August 22, 2025 - Python · from datetime import ... 2025-07-14 10:30:00+05:30 · Explanation: The function parses ISO strings with timezone offsets correctly, returning an aware datetime object....
Find elsewhere
🌐
Personmeetup
personmeetup.ca › blog › getting-iso-time-with-python-datetime
Getting ISO Time with Python Datetime - Person Meetup
from datetime import datetime current = datetime.now() print(current.isoformat()) Functionally the script is complete, but there are still some quality of life things can could be included, such as timezones and clipboard copying. That's where our previously mentioned pip packages come into play. python-dateutil extends the functionality of the built-in datetime module significantly, but we're going to use for its .tz submodule.
🌐
Python
bugs.python.org › issue35829
Issue 35829: datetime: parse "Z" timezone suffix in fromisoformat() - Python tracker
January 25, 2019 - This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/80010
Top answer
1 of 14
189

Option: isoformat()

Python's datetime does not support the military timezone suffixes like 'Z' suffix for UTC. The following simple string replacement does the trick:

In [1]: import datetime

In [2]: d = datetime.datetime(2014, 12, 10, 12, 0, 0)

In [3]: str(d).replace('+00:00', 'Z')
Out[3]: '2014-12-10 12:00:00Z'

str(d) is essentially the same as d.isoformat(sep=' ')

See: Datetime, Python Standard Library

Option: strftime()

Or you could use strftime to achieve the same effect:

In [4]: d.strftime('%Y-%m-%dT%H:%M:%SZ')
Out[4]: '2014-12-10T12:00:00Z'

Note: This option works only when you know the date specified is in UTC.

See: datetime.strftime()


Additional: Human Readable Timezone

Going further, you may be interested in displaying human readable timezone information, pytz with strftime %Z timezone flag:

In [5]: import pytz

In [6]: d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=pytz.utc)

In [7]: d
Out[7]: datetime.datetime(2014, 12, 10, 12, 0, tzinfo=<UTC>)

In [8]: d.strftime('%Y-%m-%d %H:%M:%S %Z')
Out[8]: '2014-12-10 12:00:00 UTC'
2 of 14
90

Python datetime objects don't have time zone info by default, and without it, Python actually violates the ISO 8601 specification (if no time zone info is given, assumed to be local time). You can use the pytz package to get some default time zones, or directly subclass tzinfo yourself:

from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
    def tzname(self,**kwargs):
        return "UTC"
    def utcoffset(self, dt):
        return timedelta(0)

Then you can manually add the time zone info to utcnow():

>>> datetime.utcnow().replace(tzinfo=simple_utc()).isoformat()
'2014-05-16T22:51:53.015001+00:00'

Note that this DOES conform to the ISO 8601 format, which allows for either Z or +00:00 as the suffix for UTC. Note that the latter actually conforms to the standard better, with how time zones are represented in general (UTC is a special case.)

🌐
Reddit
reddit.com › r/python › psa: as of python 3.11, `datetime.fromisoformat` supports most iso 8601 formats (notably the "z" suffix)
r/Python on Reddit: PSA: As of Python 3.11, `datetime.fromisoformat` supports most ISO 8601 formats (notably the "Z" suffix)
August 28, 2023 -

In Python 3.10 and earlier, datetime.fromisoformat only supported formats outputted by datetime.isoformat. This meant that many valid ISO 8601 strings could not be parsed, including the very common "Z" suffix (e.g. 2000-01-01T00:00:00Z).

I discovered today that 3.11 supports most ISO 8601 formats. I'm thrilled: I'll no longer have to use a third-party library to ingest ISO 8601 and RFC 3339 datetimes. This was one of my biggest gripes with Python's stdlib.

It's not 100% standards compliant, but I think the exceptions are pretty reasonable:

  • Time zone offsets may have fractional seconds.

  • The T separator may be replaced by any single unicode character.

  • Ordinal dates are not currently supported.

  • Fractional hours and minutes are not supported.

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

🌐
Pythontic
pythontic.com › datetime › datetime › isoformat
The isoformat() method of datetime class in Python | Pythontic.com
In Python the isoformat() method of datetime class returns the date-time string with the specified separator. If no separator is specified space is printed
🌐
GitHub
gist.github.com › moreati › 85de3f0745d473f54dd9076125338642
Python 3.11 datetime.datetime.fromisoformat() · GitHub
Python 3.11.8 (main, Feb 6 2024, 21:21:21) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin >>> import datetime >>> datetime.datetime.fromisoformat('2011-11-04T00:05:23.12345Z') datetime.datetime(2011, 11, 4, 0, 5, 23, 123450, tzinfo=datetime.timezone.utc) >>> datetime.datetime.fromisoformat('2011-11-04T00:05:23.1234567Z') datetime.datetime(2011, 11, 4, 0, 5, 23, 123456, tzinfo=datetime.timezone.utc) In Python 3.10 and before it only accepts exactly 6 decimal places (or no decimal point).
🌐
GeeksforGeeks
geeksforgeeks.org › isoformat-function-of-datetime-date-class-in-python
Isoformat() Function Of Datetime.date Class In Python | GeeksforGeeks
October 15, 2021 - Return values: This function returns ... day which is independent of any particular day. This class can have the tzinfo object which represents the timezone of the given time....
🌐
GitHub
github.com › python › cpython › issues › 80010
datetime: Expand scope of fromisoformat to include all of ISO 8601. · Issue #80010 · python/cpython
January 25, 2019 - assignee = None closed_at = None created_at = <Date 2019-01-25.19:36:47.536> labels = ['type-feature', 'library', '3.11'] title = 'datetime: parse "Z" timezone suffix in fromisoformat()' updated_at = <Date 2022-02-02.17:32:27.477> user = 'https://github.com/rdb' bugs.python.org fields: activity = <Date 2022-02-02.17:32:27.477> actor = 'p-ganssle' assignee = 'none' closed = False closed_date = None closer = None components = ['Library (Lib)'] creation = <Date 2019-01-25.19:36:47.536> creator = 'rdb' dependencies = [] files = [] hgrepos = [] issue_num = 35829 keywords = [] message_count = 14.0 m
Author   rdb
🌐
Python
bugs.python.org › issue46614
Issue 46614: Add option to output UTC datetimes as "Z" in `.isoformat()` - Python tracker
This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/90772
🌐
GeeksforGeeks
geeksforgeeks.org › fromisoformat-function-of-datetime-date-class-in-python
fromisoformat() Function Of Datetime.date Class In Python - GeeksforGeeks
August 23, 2021 - Example:Pythonfrom datetime import date d = date(2 ... Time class represents the local time of the day which is independent of any particular day. This class can have the tzinfo object which represents the timezone of the given time.
🌐
LabEx
labex.io › tutorials › python-how-to-create-datetime-objects-from-iso-8601-date-strings-417942
How to create datetime objects from ISO-8601 date strings | LabEx
from datetime import datetime iso_date_string = "2023-04-15T12:34:56Z" datetime_obj = datetime.fromisoformat(iso_date_string) print(datetime_obj) ## Output: 2023-04-15 12:34:56 · In this example, we first import the datetime module from the Python standard library.
🌐
Ham1
blog.ham1.co.uk › 2023 › 05 › 29 › python-parse-iso-date-with-z-at-end
Parse ISO 8601 date ending in Z with Python - Graham Russell's Blog
May 29, 2023 - We need to make the parsed datetime object timezone aware, to set it to UTC we can do the following · from datetime import datetime import pytz iso_date_string = "2023-05-29T10:30:00Z" parsed_date = datetime.fromisoformat(iso_date_string[:-1]) # Removing the 'Z' at the end utc_timezone = ...