Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can't parse parse time string with posix-style timezone in python

I have a time string like this: 2013-08-22 16:56:19 Etc/GMT

I need to parse it to a datetime object. I'm getting hung up on the posix-style time zone, which I can't get Python to natively grok.

Here are a couple of attempts and their failures. I'm including the timezone-stripped version first to show the parsing is otherwise correct.

datetime.strptime

>>> datetime.datetime.strptime("2013-08-22 16:56:19 UTC", "%Y-%m-%d %H:%M:%S %Z")
datetime.datetime(2013, 8, 22, 16, 56, 19)
>>> datetime.datetime.strptime("2013-08-22 16:56:19 Etc/GMT", "%Y-%m-%d %H:%M:%S %Z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data '2013-08-22 16:56:19 Etc/GMT' does not match format '%Y-%m-%d %H:%M:%S %Z'

time.strptime

>>> time.strptime("2013-08-22 16:56:19 UTC", "%Y-%m-%d %H:%M:%S %Z")
time.struct_time(tm_year=2013, tm_mon=8, tm_mday=22, tm_hour=16, tm_min=56, tm_sec=19, tm_wday=3, tm_yday=234, tm_isdst=0)
>>> time.strptime("2013-08-22 16:56:19 Etc/GMT", "%Y-%m-%d %H:%M:%S %Z")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 454, in _strptime_time
return _strptime(data_string, format)[0]
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data '2013-08-22 16:56:19 Etc/GMT' does not match format '%Y-%m-%d %H:%M:%S %Z'

dateutil.parser

>>> dateutil.parser.parse("2013-08-22 16:56:19")
datetime.datetime(2013, 8, 22, 16, 56, 19)
>>> dateutil.parser.parse("2013-08-22 16:56:19 Etc/GMT")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 720, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 310, in parse
    raise ValueError("unknown string format")
ValueError: unknown string format

possible solutions/avenues tried

tzinfos

It seems like dateutil's tzinfos argument should be perfect for this, but it doesn't work either... or I'm misreading the trace and doing something wrong. (I used this as an example)

>>> dateutil.parser.parse("2013-08-22 16:56:19 Etc/GMT", tzinfos={ 'Etc/GMT': pytz.timezone('UTC') })
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 720, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 310, in parse
    raise ValueError("unknown string format")
ValueError: unknown string format

tzinfos, round two

It seems like this stackoverflow answer is getting towards the usage of tzinfos that I might need. I tried the simplified version of the above (where value=offset seconds). Still fails.

>>> dateutil.parser.parse("2013-08-22 16:56:19 Etc/GMT", tzinfos={ 'Etc/GMT': 0 })
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 720, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/python_dateutil-2.1-py2.7.egg/dateutil/parser.py", line 310, in parse
    raise ValueError("unknown string format")
ValueError: unknown string format

do it the wrong way

I could always use something like regex or string matching to find and change this timezone, but it feels wrong.

red herrings

The common problem with the posix ETC/xxx timezones is that they have reversed signs. This is a UTC ("no offset") posix time zone, and many of the questions I've found that deal with "etc" have to do with this reversed offset.

like image 498
tedder42 Avatar asked Aug 22 '13 19:08

tedder42


1 Answers

How about this:

  • parse date string without the timezone part into datetime object via strptime()
  • parse timezone string into pytz timezone
  • update tzinfo on the datetime object via replace()

from datetime import datetime
import pytz

date_string = "2013-08-22 16:56:19"
tz_string = "Etc/GMT"


dt = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")
dt = dt.replace(tzinfo=pytz.timezone('Etc/GMT'))
print dt

prints:

2013-08-22 16:56:19+00:00

This actually correctly understands and reverses signs in the POSIX timezone format, for example:

dt = dt.replace(tzinfo=pytz.timezone('Etc/GMT-1'))
print dt  # prints 2013-08-22 16:56:19+01:00
like image 141
alecxe Avatar answered Oct 10 '22 13:10

alecxe