ISO to datetime object: 'z' is a bad directive [duplicate] ISO to datetime object: 'z' is a bad directive [duplicate] python python

ISO to datetime object: 'z' is a bad directive [duplicate]


Welcome to Python datetime! Dealing with dates and times is necessarily complex, and Python doesn't come fully with batteries included in this case. You can't use %z in strptime because Python has no classes to represent timezones (you are supposed to implement your own, or better yet include some other libraries).

You want to use pytz and python-dateutil. For more details see here:

Python strptime() and timezones?


problem with python 2.7

I have had a similar problem parsing commit dates from the output of git log --date=iso8601 which actually isn't the ISO8601 format (hence the addition of --date=iso8601-strict in a later version).

>>> import datetime, sys>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00", "%Y-%m-%dT%H:%M:%S.%f%z")Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 317, in _strptime    (bad_directive, format))ValueError: 'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.%f%z'>>> sys.version'2.7.10 (default, Feb  7 2017, 00:08:15) \n[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]'

problem with python 3:

If python 2 does not support %z because of the underlying strptime() implementation, then a possible way to fix your issue is to migrate to python 3. But it didn't work for me:

>>> import datetime, sys>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00", "%Y-%m-%dT%H:%M:%S.%f%z")Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 565, in _strptime_datetime    tt, fraction = _strptime(data_string, format)  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 362, in _strptime    (data_string, format))ValueError: time data '2013-07-23T15:10:59.342107+01:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'>>> sys.version'3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08) \n[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]'

The problem is because is not strictly ISO8601 (note how there was a : in the timezone info).

>>> datetime.datetime.strptime("2013-07-23T15:10:59.342107+0100", "%Y-%m-%dT%H:%M:%S.%f%z")datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=datetime.timezone(datetime.timedelta(0, 3600)))

solution with django & pytz:

Since I am using django I can leverage the utilities there.

https://github.com/django/django/blob/master/django/utils/dateparse.py

>>> from django.utils.dateparse import parse_datetime>>> parse_datetime('2013-07-23T15:10:59.342107+01:00')datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=+0100)

Instead of strptime you could use your own regular expression.

Please note that django does use pytz under the hood for things like the utc singleton.

solution without django & pytz:

If you want a quick and dirty solution, you can use something similar to django without all the requirements.

https://gist.github.com/dnozay/3cd554a818ed768bff804bc04484905d

>>> from datetime_z import parse_datetime>>> parse_datetime("2013-07-23T15:10:59.342107+01:00")datetime.datetime(2013, 7, 23, 15, 10, 59, 342107, tzinfo=+0100)

Please note: YMMV, there is no support.