【问题标题】:can't parse parse time string with posix-style timezone in python无法在 python 中使用 posix 样式的时区解析解析时间字符串
【发布时间】:2013-08-25 16:13:47
【问题描述】:

我有一个这样的时间字符串:2013-08-22 16:56:19 Etc/GMT

我需要将其解析为日期时间对象。我被 posix 风格的时区挂断了,我无法让 Python 原生地 grok。

这里有几个尝试和他们的失败。我首先包含时区剥离版本,以显示解析在其他方面是正确的。

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

尝试了可能的解决方案/途径

tzinfos

似乎dateutil's tzinfos argument 应该是完美的,但它也不起作用......或者我误读了跟踪并做错了什么。 (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,第二轮

似乎this stackoverflow answer 正在使用我可能需要的 tzinfos。我尝试了上述的简化版本(其中 value=offset seconds)。还是失败了。

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

做错了

我总是可以使用正则表达式或字符串匹配之类的东西来查找和更改这个时区,但感觉错误

红鲱鱼

posix ETC/xxx 时区的常见问题是they have reversed signs。这是一个 UTC(“无偏移”)posix 时区,我发现处理“etc”的许多问题都与这个反向偏移有关。

【问题讨论】:

  • Python 在任何情况下都不能很好地理解时区,在 python 中使用时区就像想朝自己的脚开枪,但无法做到,反而朝自己的头开枪。

标签: python datetime timezone posix


【解决方案1】:

这个怎么样:

  • 通过strptime()将不带时区部分的日期字符串解析为datetime对象
  • 将时区字符串解析为pytz时区
  • 通过replace()更新日期时间对象上的tzinfo

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

打印:

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

这实际上正确理解并反转了 POSIX 时区格式的符号,例如:

dt = dt.replace(tzinfo=pytz.timezone('Etc/GMT-1'))
print dt  # prints 2013-08-22 16:56:19+01:00

【讨论】:

  • 要将字符串分成两部分,我必须匹配该确切字符串或尝试近似它。这对我来说属于“以错误的方式做”,但这是一种选择。
  • 好吧,pytz 处理这种时区格式。我认为这是您的一个选择。
  • 问题是知道那些 TZ 可能是什么来将字符串分开。不过,这可能是最好的选择。非常感谢您的回答。
  • @tedder42:使用tz.localize(dt) 而不是dt.replace(tzinfo=tz)(后者在许多时区都失败(尽管它适用于UTC)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
  • 2019-11-08
  • 2013-07-14
  • 1970-01-01
相关资源
最近更新 更多