This question already has an answer here:
I am trying to convert ISO to datetime
using the code below:
dt = datetime.datetime.strptime("2013-07-23T15:10:59.342107+01:00",
"%Y-%m-%dT%H:%M:%S.%f%z")
and I'm getting the error below:
'z' is a bad directive in format '%Y-%m-%dT%H:%M:%S.%f%z'
What is the best way to convert an ISO string of above the format to a datetime
object? I'm using Python version 2.7.6.
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:
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.
来源:https://stackoverflow.com/questions/20194496/iso-to-datetime-object-z-is-a-bad-directive