Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert timestamps with offset to datetime obj using strptime

I am trying to convert time-stamps of the format "2012-07-24T23:14:29-07:00" to datetime objects in python using strptime method. The problem is with the time offset at the end(-07:00). Without the offset i can successfully do

time_str = "2012-07-24T23:14:29"  time_obj=datetime.datetime.strptime(time_str,'%Y-%m-%dT%H:%M:%S') 

But with the offset i tried

time_str = "2012-07-24T23:14:29-07:00"  time_obj=datetime.datetime.strptime(time_str,'%Y-%m-%dT%H:%M:%S-%z'). 

But it gives a Value error saying "z" is a bad directive.

Any ideas for a work around?

like image 811
auny Avatar asked Sep 05 '12 12:09

auny


People also ask

What does datetime Strptime return?

The strptime() function in Python is used to format and return a string representation of date and time. It takes in the date, time, or both as an input, and parses it according to the directives given to it.

What is the difference between Strptime and Strftime?

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.

How do I use Strftime and Strptime in Python?

Python time strptime() MethodThe format parameter uses the same directives as those used by strftime(); it defaults to "%a %b %d %H:%M:%S %Y" which matches the formatting returned by ctime(). If string cannot be parsed according to format, or if it has excess data after parsing, ValueError is raised.

What does Strptime mean?

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


2 Answers

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 parse time_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))) 
like image 124
Martijn Pieters Avatar answered Sep 30 '22 11:09

Martijn Pieters


In Python 3.7+:

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

where FixedOffset class is defined here.

like image 20
jfs Avatar answered Sep 30 '22 10:09

jfs