问题
Currently we are working on an application which is trying to calculate the travel time of a route from a to b, using the 2.db.transport.rest API.
Unfortunatly we are receiving timestamps with a timezone offset from that API, such as +01:00
. What we need is a timezone offset without the :
, so +0100
.
The following example gives an error on Linux, using Python 3.6.7:
from datetime import datetime
datetimestring = "2019-01-19T15:13:00.000+01:00"
datetime.strptime(datetimestring, '%Y-%m-%dT%H:%M:%S.%f%z')
This example code produces this exception:
ValueError: time data '2019-01-19T15:13:00.000+01:00' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
If we remove the :
from the input string it works, no exception is thrown.
The code also works when we run this on Windows, on Python 3.7.2.
Could it be due to the different Python versions? How can we parse or convert this without error?
回答1:
Yes, this is a version problem. You are relying on a new feature introduced in Python 3.7
From the datetime.strptime() documentation, 6th footnote:
Changed in version 3.7: When the
%z
directive is provided to thestrptime()
method, the UTC offsets can have a colon as a separator between hours, minutes and seconds. For example,'+01:00:00'
will be parsed as an offset of one hour.
If you can't upgrade to Python 3.7 everywhere, then you could just remove those colons with some preprocessing:
import re
datetimestring = re.sub(r'([-+]\d{2}):(\d{2})(?:(\d{2}))?$', r'\1\2\3', datetimestring)
The regex removes the colons from any HH:MM
or HH:MM:SS
offset (appearing at the
end of a string and preceded by -
or +
):
Demo:
>>> import re
>>> from datetime import datetime
>>> datetimestring = "2019-01-19T15:13:00.000+01:00"
>>> corrected = re.sub(r'([-+]\d{2}):(\d{2})(?:(\d{2}))?$', r'\1\2\3', datetimestring)
>>> corrected
'2019-01-19T15:13:00.000+0100'
>>> datetime.strptime(corrected, '%Y-%m-%dT%H:%M:%S.%f%z')
datetime.datetime(2019, 1, 19, 15, 13, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600)))
If you were to upgrade to Python 3.7 everywhere, you could drop the strptime()
parsing altogether and simply use the dedicated datetime.fromisoformat() method; it can parse your input directly.
>>> datetime.fromisoformat(datetimestring)
datetime.datetime(2019, 1, 19, 15, 13, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600)))
来源:https://stackoverflow.com/questions/54268458/datetime-strptime-issue-with-a-timezone-offset-with-colons