关于datetime:Python strptime()和timezones?

Python strptime() and timezones?

我有一个使用IPDDump创建的Blackberry IPD备份的CSV转储文件。
这里的日期/时间字符串看起来像这样
(其中EST是澳大利亚时区):

1
Tue Jun 22 07:46:22 EST 2010

我需要能够在Python中解析这个日期。 起初,我尝试使用datettime中的strptime()函数。

1
>>> datetime.datetime.strptime('Tue Jun 22 12:10:20 2010 EST', '%a %b %d %H:%M:%S %Y %Z')

但是,由于某种原因,返回的datetime对象似乎没有与之关联的tzinfo

我在这个页面上看到显然datetime.strptime默默地丢弃了tzinfo,但是,我检查了文档,我找不到任何有关此处记录的效果。

我已经能够使用第三方Python库dateutil来解析日期,但是我仍然很好奇我是如何错误地使用内置的strptime()的? 有没有办法让strptime()与时区很好地配合?


我建议使用python-dateutil。它的解析器已经能够解析到目前为止我抛出的每种日期格式。

1
2
3
4
5
6
7
8
9
>>> from dateutil import parser
>>> parser.parse("Tue Jun 22 07:46:22 EST 2010")
datetime.datetime(2010, 6, 22, 7, 46, 22, tzinfo=tzlocal())
>>> parser.parse("Fri, 11 Nov 2011 03:18:09 -0400")
datetime.datetime(2011, 11, 11, 3, 18, 9, tzinfo=tzoffset(None, -14400))
>>> parser.parse("Sun")
datetime.datetime(2011, 12, 18, 0, 0)
>>> parser.parse("10-11-08")
datetime.datetime(2008, 10, 11, 0, 0)

等等。没有处理strptime()格式的废话...只是在它上面抛出一个日期,它是正确的事情。

更新:哎呀。我在你原来的问题中错过了你提到你使用dateutil,抱歉。但我希望这个答案对于那些在解析问题并查看该模块的实用程序时遇到这个问题的人来说仍然有用。


datetime模块文档说:

Return a datetime corresponding to date_string, parsed according to format. This is equivalent to datetime(*(time.strptime(date_string, format)[0:6])).

看到[0:6]?这会让你(year, month, day, hour, minute, second)。没有其他的。没有提到时区。

有趣的是,[Win XP SP2,Python 2.6,2.7]将您的示例传递给time.strptime不起作用,但如果您剥离"%Z"和"EST"它确实有效。也使用"UTC"或"GMT"代替"EST"。"PST"和"MEZ"不起作用。令人费解。

值得注意的是,自版本3.2起已更新,现在相同的文档也说明如下:

When the %z directive is provided to the strptime() method, an aware datetime object will be produced. The tzinfo of the result will be set to a timezone instance.

请注意,这不适用于%Z,因此这种情况很重要。请参阅以下示例:

1
2
3
4
5
6
7
8
9
10
11
In [1]: from datetime import datetime

In [2]: start_time = datetime.strptime('2018-04-18-17-04-30-AEST','%Y-%m-%d-%H-%M-%S-%Z')

In [3]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: None

In [4]: start_time = datetime.strptime('2018-04-18-17-04-30-+1000','%Y-%m-%d-%H-%M-%S-%z')

In [5]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: UTC+10:00


您的时间字符串类似于rfc 2822中的时间格式(电子邮件中的日期格式,http标头)。你可以只使用stdlib解析它:

1
2
3
>>> from email.utils import parsedate_tz
>>> parsedate_tz('Tue Jun 22 07:46:22 EST 2010')
(2010, 6, 22, 7, 46, 22, 0, 1, -1, -18000)

查看为各种Python版本生成时区感知日期时间对象的解决方案:使用电子邮件中的时区解析日期。

在这种格式中,EST在语义上等同于-0500。虽然,通常,时区缩写是不够的,但要唯一地标识时区。