Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Datetime strptime issue with a timezone offset with colons [duplicate]

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?

like image 582
Bruno Avatar asked Jan 19 '19 15:01

Bruno


People also ask

What does DateTime DateTime Strptime do?

Python DateTime – strptime() Function strptime() is another method available in DateTime which is used to format the time stamp which is in string format to date-time object.

What does Strptime mean?

The strptime() function converts the character string pointed to by buf to values which are stored in the tm structure pointed to by tm, using the format specified by format. The format is composed of zero or more directives.

What is the difference between Strftime and Strptime in Python?

strptime is short for "parse time" where strftime is for "formatting time". That is, strptime is the opposite of strftime though they use, conveniently, the same formatting specification.

What does DateTime Strptime return?

Description. Python time method strptime() parses a string representing a time according to a format. The return value is a struct_time as returned by gmtime() or localtime().


1 Answers

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 the strptime() 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)))
like image 90
Martijn Pieters Avatar answered Sep 29 '22 10:09

Martijn Pieters