Python strptime()和时区?

vic*_*ooi 141 python timezone datetime

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

Tue Jun 22 07:46:22 EST 2010
Run Code Online (Sandbox Code Playgroud)

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

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

但是,由于某种原因,返回的datetime对象似乎没有任何tzinfo关联它.

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

我已经能够使用第三方Python库dateutil来解析日期,但是我仍然很好奇我是如何使用内置strptime()错误的?有什么方法可以strptime()很好地与时区玩吗?

Joe*_*haw 334

我建议使用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)
Run Code Online (Sandbox Code Playgroud)

等等.没有处理strptime()格式无意义...只是在它上面的日期,它是正确的事情.

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

  • @flyingfoxlee,是的,我理解.我只想告诉人们python-dateutil的局限性.它做了神奇的事情,但有时却做不到.所以"只是在它上面约会,它就是正确的事情." 不是100%真实. (7认同)
  • ```dateutil.parser.parse("10-27-2016 09:06 AM PDT")```返回:```datetime.datetime(2016,10,27,9,6)```无法计算出时区... (3认同)
  • 这取决于一个人的目标。`dateutil parser` 可能使用起来很简单,但 `strptime()` 更快。此外,它的格式很容易学习。 (3认同)
  • @wanghq,您需要将最后一个逗号替换为句点。然后 `parser.parse("Thu, 25 Sep 2003 10:49:41.123 -0300") 返回: datetime.datetime(2003, 9, 25, 10, 49, 41, 123000, tzinfo=tzoffset(None, -10800) )` (2认同)

Joh*_*hin 47

datetime模块的文件说:

返回与date_string对应的日期时间,根据格式进行解析.这相当于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起已更新,现在相同的文档也说明如下:

当%z指令提供给strptime()方法时,将生成一个知道的datetime对象.结果的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
Run Code Online (Sandbox Code Playgroud)

  • 相关的Python bug:[strptime中的%Z与EST和其他人不匹配](http://bugs.python.org/issue22377) (11认同)

Sur*_*eja 41

由于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'
Run Code Online (Sandbox Code Playgroud)

  • @iudeen 您所描述的是错误本地化的“pytz”时区对象的结果。使用 pytz,您*必须*本地化,不要使用替换!然而,对于 Python 3.9,您应该使用 [zoneinfo](https://docs.python.org/3/library/zoneinfo.html),这样可以完全避免这个陷阱。在那里“更换”是安全的。 (7认同)
  • 并非所有时间戳字符串都是基于 UTC 的(例如问题中的字符串)。 (2认同)
  • 这对于许多时区来说无法正常工作。例如:对“Asia/Kolkata”执行此操作会给出“tzinfo=<DstTzInfo 'Asia/Kolkata' LMT+5:53:00 STD”的偏移量 (2认同)

jfs*_*jfs 9

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

>>> 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)
Run Code Online (Sandbox Code Playgroud)

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

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