使用strptime时日期格式不正确

3

可能是重复问题:
Python strptime() 和时区?

'Saturday, December 22, 2012 1:22:24 PM EST' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'

也许我漏看了什么,但有人能发现为什么这不能正确验证吗?
4个回答

2
strptime()函数无法很好地处理%Z时区解析。只支持UTC、GMT和当前的time.tzname值。请参见strptime文档

%Z指令的支持基于tzname中包含的值以及daylight是否为真。因此,它是特定于平台的,除了识别始终已知的UTC和GMT(并被认为是非夏令时区域)。

删除输入中的EST部分和格式字符串中的%Z部分可以使事情正常工作。
>>> import time
>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM EST', '%A, %B %d, %Y %I:%M:%S %p %Z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 454, in _strptime_time
    return _strptime(data_string, format)[0]
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data 'Saturday, December 22, 2012 1:22:24 PM EST' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'
>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM', '%A, %B %d, %Y %I:%M:%S %p')
time.struct_time(tm_year=2012, tm_mon=12, tm_mday=22, tm_hour=13, tm_min=22, tm_sec=24, tm_wday=5, tm_yday=357, tm_isdst=-1)

或者将时区EST替换为GMT

>>> time.strptime('Saturday, December 22, 2012 1:22:24 PM GMT', '%A, %B %d, %Y %I:%M:%S %p %Z')
time.struct_time(tm_year=2012, tm_mon=12, tm_mday=22, tm_hour=13, tm_min=22, tm_sec=24, tm_wday=5, tm_yday=357, tm_isdst=0)

如果要解析具有不同于time.tznameGMTUTC时区的字符串,请使用其他日期解析库。 dateutil 具有出色的parse函数,可以正确处理时区:

>>> from dateutil.parser import parse
>>> parse('Saturday, December 22, 2012 1:22:24 PM EST', tzinfos={'EST': -18000})
datetime.datetime(2012, 12, 22, 13, 22, 24, tzinfo=tzoffset(u'EST', -18000))

使用dateutil.parser.parse()时,您需要为您的格式提供自己的时区偏移量。

日期解析器仅对上述情况提供正确的datetime对象。但请考虑以下情况,`>>> parse('Saturday, 13-12-11 1:22:24 PM EST', tzinfos={'EST': -18000}) datetime.datetime(2011, 12, 13, 13, 22, 24, tzinfo=tzoffset('EST', -18000))
parse('Saturday, 09-12-11 1:22:24 PM EST', tzinfos={'EST': -18000}) datetime.datetime(2011, 9, 12, 13, 22, 24, tzinfo=tzoffset('EST', -18000))`。两种情况下datetimeobject.date()不同。
- Darknight
1
@PSivachandran:这是因为日期不明确。一年只有12个月,所以第一个例子中格式是日-月-年的顺序很清楚,但第二个例子可以被解释为日-月-年和月-日-年两种方式。默认情况下,解析日期的方式是后者,您可以使用dayfirst=True关键字来更改。 - Martijn Pieters
@Marijn:太好了,谢谢。我不知道这个dayfirst关键字,没有它我完全懵逼了。你的解释很棒,点赞! - Darknight

1

您可以使用dateutil,这样可以避免很多麻烦。

In [1]: from dateutil import parser

In [2]: parser.parse('Saturday, December 22, 2012 1:22:24 PM EST')
Out[2]: datetime.datetime(2012, 12, 22, 13, 22, 24)

关于eumiro指出的不确定性,您可以添加一个tzinfo参数:
In [3]: parser.parse('Saturday, December 22, 2012 1:22:24 PM EST',tzinfos={'EST':-5*3600})
Out[3]: datetime.datetime(2012, 12, 22, 13, 22, 24, tzinfo=tzoffset('EST', -18000))

问题仍然存在。它忽略了EST时区(正确的,因为它既可以是美国,也可以是澳大利亚:http://www.timeanddate.com/library/abbreviations/timezones/)。 - eumiro
1
@ eumiro - 你是对的。我认为在解析时可能需要添加 tzinfos 参数来处理它。 - root
太棒了,我不知道tzinfos - eumiro

1

正如@root所建议的那样,dateutil.parser是解析日期的强大方式,但是为了澄清这里的问题

我刚刚看到_strptime.py中的代码,似乎支持的时区是

["utc", "gmt", time.tzname[0].lower()]

如果当前区域设置的时区支持夏令时,则会将time.tzname[0].lower()添加到上述列表中。

因此,在使用strptime时,请确保解析日期的时区支持源时区。

以下是参考代码:

def __calc_timezone(self):
    # Set self.timezone by using time.tzname.
    # Do not worry about possibility of time.tzname[0] == timetzname[1]
    # and time.daylight; handle that in strptime .
    try:
        time.tzset()
    except AttributeError:
        pass
    no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()])
    if time.daylight:
        has_saving = frozenset([time.tzname[1].lower()])
    else:
        has_saving = frozenset()
    self.timezone = (no_saving, has_saving)

0

很可能您的本地时区为空,例如%Z计算结果为'' 您可以通过以下方式进行测试:

>>> fmt = '%A, %B %d, %Y %I:%M:%S %p %Z'
>>> datetime.strptime(datetime.strftime(datetime.now(), fmt), fmt)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data 'Friday, December 28, 2012 11:34:35 AM ' does not match format '%A, %B %d, %Y %I:%M:%S %p %Z'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接