Parse "Z" timezone suffix in datetime

Most have been said here already, just wanted to add that I also arrived at this page after receiving JSON data from a JavaScript application.

Also, using dateutil gives a slightly different result. Compare:

import dateutil.parser as dt
date_time_obj = dt.parse('2020-02-25T13:13:43.913Z')
date_time_obj
# out: datetime.datetime(2020, 2, 25, 13, 13, 43, 913000, tzinfo=tzutc())
date_time_obj2 = datetime.fromisoformat('2020-02-25T13:13:43.913Z'.replace('Z', '+00:00'))
date_time_obj2
# out: datetime.datetime(2020, 2, 25, 13, 13, 43, 913000, tzinfo=datetime.timezone.utc)

A difference in tzinfo with tzutc() vs datetime.timezone.utc.
Although that doesn’t seem to be a problem:

date_time_obj == date_time_obj2
# out: True

It would be really useful if the documentation explicitly stated that Z is not parsed and must be replaced with +00:00

2 Likes

I think one thing that might be worth to add is that Django’s DjangoJSONEncoder also uses ‘Z’. This is the reason that I ended up here.

So it’s not just other popular languages like Javascript that uses the format. One of the most popular Python web frameworks uses it for JSON encoding datetimes.

2 Likes

I wanted to note that the replace('Z', '00+00') workaround makes parsing dates around 5x as slow (I ran a benchmark of various date parsing libraries and functions; see linked gist).

I think having a very fast ISO parsing function in the python standard library is important.

Date parsing benchmark (requires packages: pytest, pytest-benchmark, python-dateutil, ciso8601, iso8601)

1 Like

Another gotcha is that datetime.datetime.fromisoformat is picky about fractional seconds:

  • 2020-01-01T12:33:56 :white_check_mark:
  • 2020-01-01T12:33:56.0 :x:
  • 2020-01-01T12:33:56.000 :white_check_mark: (milliseconds)
  • 2020-01-01T12:33:56.0000 :x:
  • 2020-01-01T12:33:56.000000 :white_check_mark: (microseconds)
  • 2020-01-01T12:33:56.00000 :x: # commonly generated by JavaScript libraries
  • 2020-01-01T12:33:56.0000000 :x:
  • 2020-01-01T12:33:56.000000000 :x: (nanoseconds) # golang, tc39 Temporal
2 Likes