Convert timestamps with offset to datetime obj using strptime Convert timestamps with offset to datetime obj using strptime python python

Convert timestamps with offset to datetime obj using strptime


The Python 2 strptime() function indeed does not support the %z format for timezones (because the underlying time.strptime() function doesn't support it). You have two options:

  • Ignore the timezone when parsing with strptime:

    time_obj = datetime.datetime.strptime(time_str[:19], '%Y-%m-%dT%H:%M:%S')
  • use the dateutil module, it's parse function does deal with timezones:

    from dateutil.parser import parsetime_obj = parse(time_str)

Quick demo on the command prompt:

>>> from dateutil.parser import parse>>> parse("2012-07-24T23:14:29-07:00")datetime.datetime(2012, 7, 24, 23, 14, 29, tzinfo=tzoffset(None, -25200))

You could also upgrade to Python 3.2 or newer, where timezone support has been improved to the point that %z would work, provided you remove the last : from the input, and the - from before the %z:

>>> import datetime>>> time_str = "2012-07-24T23:14:29-07:00">>> datetime.datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S%z')Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python3.4/_strptime.py", line 500, in _strptime_datetime    tt, fraction = _strptime(data_string, format)  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python3.4/_strptime.py", line 337, in _strptime    (data_string, format))ValueError: time data '2012-07-24T23:14:29-07:00' does not match format '%Y-%m-%dT%H:%M:%S%z'>>> ''.join(time_str.rsplit(':', 1))'2012-07-24T23:14:29-0700'>>> datetime.datetime.strptime(''.join(time_str.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')datetime.datetime(2012, 7, 24, 23, 14, 29, tzinfo=datetime.timezone(datetime.timedelta(-1, 61200)))


In Python 3.7+:

from datetime import datetimetime_str = "2012-07-24T23:14:29-07:00"dt_aware = datetime.fromisoformat(time_str)print(dt_aware.isoformat('T'))# -> 2012-07-24T23:14:29-07:00

In Python 3.2+:

from datetime import datetimetime_str = "2012-07-24T23:14:29-0700"dt_aware = datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S%z')print(dt_aware.isoformat('T'))# -> 2012-07-24T23:14:29-07:00

Note: Before Python 3.7 this variant didn't support : in the -0700 part (both formats are allowed by rfc 3339). See datetime: add ability to parse RFC 3339 dates and times.

On older Python versions such as Python 2.7, you could parse the utc offset manually:

from datetime import datetimetime_str = "2012-07-24T23:14:29-0700"# split the utc offset partnaive_time_str, offset_str = time_str[:-5], time_str[-5:]# parse the naive date/time partnaive_dt = datetime.strptime(naive_time_str, '%Y-%m-%dT%H:%M:%S')# parse the utc offsetoffset = int(offset_str[-4:-2])*60 + int(offset_str[-2:])if offset_str[0] == "-":   offset = -offsetdt = naive_dt.replace(tzinfo=FixedOffset(offset))print(dt.isoformat('T'))

where FixedOffset class is defined here.


ValueError: 'z' is a bad directive in format...

(note: I have to stick to python 2.7 in my case)

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).

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.