How to Translate an Iso 8601 Datetime String into a Python Datetime Object

How do I translate an ISO 8601 datetime string into a Python datetime object?

I prefer using the dateutil library for timezone handling and generally solid date parsing. If you were to get an ISO 8601 string like: 2010-05-08T23:41:54.000Z you'd have a fun time parsing that with strptime, especially if you didn't know up front whether or not the timezone was included. pyiso8601 has a couple of issues (check their tracker) that I ran into during my usage and it hasn't been updated in a few years. dateutil, by contrast, has been active and worked for me:

from dateutil import parser
yourdate = parser.parse(datestring)

Converting string formatted ISO date to Epoch in Python

dateutil is your friend, also with 7 digits of fractional seconds:

from dateutil.parser import isoparse

isoparse("2021-12-14T12:05:51.8031499")
Out[2]: datetime.datetime(2021, 12, 14, 12, 5, 51, 803149)

isoparse("2021-12-14T12:05:51.8031499").timestamp()
Out[3]: 1639479951.803149

Note: given ISO format date/time will result in a naive datetime object, which Python will treat as local time, i.e. it will be converted from your machine's local time setting to UTC before Unix time is calculated for timestamp() !

How to convert this date string into a datetime date object?

%Z is the wrong directive here.

Try this

datetime.strptime('2013-11-05T20:24:51+0000', '%Y-%m-%dT%H:%M:%S+%f')

More here

Demo:

>>> from datetime import datetime
>>> datetime.strptime('2013-11-05T20:24:51+0000', '%Y-%m-%dT%H:%M:%S%Z')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '2013-11-05T20:24:51+0000' does not match format '%Y-%m-%dT%H:%M:%S%Z'
>>> datetime.strptime('2013-11-05T20:24:51+0000', '%Y-%m-%dT%H:%M:%S+%f')
datetime.datetime(2013, 11, 5, 20, 24, 51)

Fastest datetime to ISO8601 translator

I have benchmarked all the different methods I could find with the following results:

  • datetime.strftime - Time for 1000000 loops: 9.262935816994286
  • cast to string - Time for 1000000 loops: 4.381643378001172
  • datetime isoformat - Time for 1000000 loops: 4.331578577999608
  • pendulum to_iso8601_string - Time for 1000000 loops: 18.471532950992696
  • rfc3339 - Time for 1000000 loops: 24.731586036010412

The code to generate this is:

import timeit
from datetime import datetime
from pendulum import datetime as pendulum_datetime
from rfc3339 import rfc3339

dt = datetime(2011, 11, 4, 0, 5, 23, 283000)
pendulum_dt = pendulum_datetime(2011, 11, 4, 0, 5, 23, 283000)

repeats = 10**6

print('datetime strftime')
func1 = lambda: datetime.strftime(dt, "%Y-%m-%dT%H:%M:%S.%f%z")
print(func1())
print('Time for {0} loops: {1}'.format(
repeats, timeit.timeit(func1, number=repeats))
)

print('cast to string')
func2 = lambda: str(dt)
print(func2())
print('Time for {0} loops: {1}'.format(
repeats, timeit.timeit(func2, number=repeats))
)

print('datetime isoformat')
func3 = lambda: datetime.isoformat(dt)
print(func3())
print('Time for {0} loops: {1}'.format(
repeats, timeit.timeit(func3, number=repeats))
)

print('pendulum to_iso8601_string')
func4 = lambda: pendulum_dt.to_iso8601_string()
print(func4())
print('Time for {0} loops: {1}'.format(
repeats, timeit.timeit(func4, number=repeats))
)

print('rfc3339')
func5 = lambda: rfc3339(dt)
print(func5())
print('Time for {0} loops: {1}'.format(
repeats, timeit.timeit(func5, number=repeats))
)

How to convert Python's .isoformat() string back into datetime object

Python 3.7+

As of Python 3.7 there is a method datetime.fromisoformat() which is exactly the reverse for isoformat().

Older Python

If you have older Python, then this is the current best "solution" to this question:

pip install python-dateutil

Then...

import datetime
import dateutil

def getDateTimeFromISO8601String(s):
d = dateutil.parser.parse(s)
return d

Python: Parse ISO 8601 date and time from a string (using the standard modules)

No need for a regexp, use datetime.datetime.strptime() instead.



Related Topics



Leave a reply



Submit