如何在使用strptime()解析日期/时间字符串时保留时区?

264 投票
5 回答
346802 浏览
提问于 2025-04-16 01:40

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

Tue Jun 22 07:46:22 EST 2010

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

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

但是,奇怪的是,返回的datetime对象似乎没有任何tzinfo信息。

我在这个页面上看到,似乎datetime.strptime在处理时区信息时会悄悄地丢弃tzinfo,不过我查了文档,没找到相关的说明在这里

有没有什么办法让strptime()能正确处理时区呢?

5 个回答

106

因为 strptime 函数返回的是一个日期时间对象,这个对象里面有一个叫 tzinfo 的属性,所以我们可以很简单地把它换成我们想要的时区。

>>> import datetime

>>> date_time_str = '2018-06-29 08:15:27.243860'
>>> date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f').replace(tzinfo=datetime.timezone.utc)
>>> date_time_obj.tzname()
'UTC'
446

我推荐使用 python-dateutil 这个库。到目前为止,我给它的每种日期格式,它都能正确解析。

>>> 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() 那些复杂的格式问题……只要把日期给它,它就能正确处理。

94

datetime模块的文档里说:

根据格式解析日期字符串,返回一个对应的日期时间。这相当于 datetime(*(time.strptime(date_string, format)[0:6]))

你看到那个 [0:6] 吗?它会给你 (年, 月, 日, 时, 分, 秒)。就这些,没有其他的。也没有提到时区。

有趣的是,在[Win XP SP2, Python 2.6, 2.7]环境下,把你的例子传给 time.strptime 是不工作的,但如果你去掉 " %Z" 和 " EST",就可以正常工作了。而且用 "UTC" 或 "GMT" 代替 "EST" 也可以工作。"PST" 和 "MEZ" 就不行了。这让人困惑。

值得注意的是,从3.2版本开始,这个内容有了更新,现在文档里还说:

当在strptime()方法中提供了 %z 指令时,会生成一个带时区的日期时间对象。结果的 tzinfo 会被设置为一个时区实例。

请注意,这个在 %Z 的情况下不适用,所以大小写是很重要的。看看下面的例子:

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

撰写回答