我的datetime.strptime格式有什么问题?

3

使用该函数:

timestamp = datetime.strptime(date_str, date_fmt)

我遇到了这个错误:
ValueError: 时间数据 'Sun, 28 Oct 2018 07:33:13 -0400 (EDT)' 与格式 '%a, %d %b %Y %H:%M:%S %z (%Z)' 不匹配。
Sun, 28 Oct 2018 07:33:13 -0400 (EDT)
%a, %d %b %Y %H:%M:%S %z (%Z)

我已经看了十多遍,但是我无法弄清楚我做错了什么。

我的Python版本:

Python 3.7.0 (default, Jul 23 2018, 20:24:19) 

它适用于 (UTC)。EDT 是一个有效的区域吗? - Jean-François Fabre
https://www.timeanddate.com/time/zones/edt - Python 不认识它吗? - Adam Starrh
我的正则表达式匹配模式是 ('(?P<a>mon|tue|wed|thu|fri|sat|sun),\\s+(?P<d>3[0-1]|[1-2]\\d|0[1-9]|[1-9]| ' '[1-9])\\s+(?P<b>jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\\s+(?P<Y>\\d\\d\\d\\d)\\s+(?P<H>2[0-3]|[0-1]\\d|\\d):(?P<M>[0-5]\\d|\\d):(?P<S>6[0-1]|[0-5]\\d|\\d)\\s+(?P<z>[+-]\\d\\d[0-5]\\d)\\s+\\((?P<Z>paris\\,\\ ' 'madrid\\ \\(heure\\ d\\\x92\\ét\\é\\)|paris\\,\\ madrid|utc|gmt)\\)') 它取决于当前的时区。 - Jean-François Fabre
1个回答

9

除了当前时区之外,输入中不支持%Z的任何内容。只有time.tzname元组中的字符串加上'UTC''GMT'才会被识别:

>>> from datetime import datetime
>>> import time
>>> time.tzname
('GMT', 'BST')
>>> sample = 'Sun, 28 Oct 2018 07:33:13 -0400 (EDT)'
>>> datetime.strptime(sample.replace('EDT', time.tzname[0]), '%a, %d %b %Y %H:%M:%S %z (%Z)')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'GMT'))
>>> datetime.strptime(sample.replace('EDT', time.tzname[1]), '%a, %d %b %Y %H:%M:%S %z (%Z)')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), 'BST'))

即使您在输入中使用了“已知”的时区名称,除非还有一个时区偏移量(%z),否则该名称将被忽略;使用%z偏移量仅用于设置从%z偏移量构建的{{link1:datetime.timezone()实例}}的name参数。

不幸的是,这种行为并没有得到明确记录,请参阅Python问题{{link2:#22377}}和{{link3:#22426}}。文档似乎暗示EST应该是%Z可解析的可接受值,但文档的这部分仅显示 datetime.strftime()字符串输出,而不是可接受的datetime.strptime()字符串输入。

由于您在字符串中还具有相对于UTC的偏移量(-0400部分),因此只需将时区名称从输入中删除,并且不要尝试解析它:

>>> datetime.strptime(sample.rpartition(' ')[0], '%a, %d %b %Y %H:%M:%S %z')
datetime.datetime(2018, 10, 28, 7, 33, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

我在这里使用了 str.rpartition() 来删除从最后一个空格开始的所有内容,但是最好根据您的输入类型来确定如何最好地在应用程序中删除时区名称部分。没有它,(%Z) 部分是不需要的,您将得到一个正确的 datetime 对象。
在调试 datetime.strptime() 问题时,您需要将问题进行“分隔”。您可以对输入和模板部分进行二分,以查看问题所在,或者逐个尝试不同的组件。可能是单个指令引起了问题,也可能是多个,因此我通常会一步一步地删除指令,直到找到有效的一个。

对于那些对datetime.strptime()的工作细节感兴趣的人,您可以使用调试器进入调用,因为实现使用纯Python模块。对于datetime.strptime(),入口点是_strptime._strptime_datetime(),而%Z参数匹配模式是由这个小循环生成的,其中self.locale_time.timezone是一个包含3个字母字符串的frozensets的2值元组,它是通过LocaleTime.__calc_timezone()方法设置的。


我没有意识到这一点。好的,如果它存在,我会从字符串中将其删除,谢谢。 - Adam Starrh
那么,如果它不支持非本地时区,UTC 是否是内置的例外? - Adam Starrh
1
@AdamStarrh:是的,字符串'UTC'也适用于%Z%Z只匹配一组非常有限的字符串。 - Martijn Pieters

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