Python strptime() 和时区?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3305413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:22:27  来源:igfitidea点击:

Python strptime() and timezones?

pythondatetimetimezone

提问by victorhooi

I have a CSV dumpfile from a Blackberry IPD backup, created using IPDDump. The date/time strings in here look something like this (where ESTis an Australian time-zone):

我有一个来自 Blackberry IPD 备份的 CSV 转储文件,它是使用 IPDDump 创建的。此处的日期/时间字符串如下所示(其中EST是澳大利亚时区):

Tue Jun 22 07:46:22 EST 2010

I need to be able to parse this date in Python. At first, I tried to use the strptime()function from datettime.

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

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

However, for some reason, the datetimeobject that comes back doesn't seem to have any tzinfoassociated with it.

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

I did read on this pagethat apparently datetime.strptimesilently discards tzinfo, however, I checked the documentation, and I can't find anything to that effect documented here.

我确实在这个页面上读过,显然是datetime.strptime默默地丢弃了tzinfo,但是,我检查了文档,我找不到任何与此相关的内容

I have been able to get the date parsed using a third-party Python library, dateutil, however I'm still curious as to how I was using the in-built strptime()incorrectly? Is there any way to get strptime()to play nicely with timezones?

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

采纳答案by John Machin

The datetimemodule documentationsays:

datetime模块的文件说:

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

返回 date_string 对应的日期时间,按照格式解析。这相当于datetime(*(time.strptime(date_string, format)[0:6])).

See that [0:6]? That gets you (year, month, day, hour, minute, second). Nothing else. No mention of timezones.

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

Interestingly, [Win XP SP2, Python 2.6, 2.7] passing your example to time.strptimedoesn't work but if you strip off the " %Z" and the " EST" it does work. Also using "UTC" or "GMT" instead of "EST" works. "PST" and "MEZ" don't work. Puzzling.

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

It's worth noting this has been updated as of version 3.2 and the same documentation now also states the following:

值得注意的是,这已从 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 指令提供给 strptime() 方法时,将生成一个感知日期时间对象。结果的 tzinfo 将设置为时区实例。

Note that this doesn't work with %Z, so the case is important. See the following example:

请注意,这不适用于 %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

回答by Joe Shaw

I recommend using python-dateutil. Its parser has been able to parse every date format I've thrown at it so far.

我建议使用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)

and so on. No dealing with strptime()format nonsense... just throw a date at it and it Does The Right Thing.

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

Update: Oops. I missed in your original question that you mentioned that you used dateutil, sorry about that. But I hope this answer is still useful to other people who stumble across this question when they have date parsing questions and see the utility of that module.

更新:哎呀。我错过了您提到的您使用的原始问题dateutil,对此感到抱歉。但我希望这个答案对其他人在遇到日期解析问题并看到该模块的效用时偶然发现这个问题仍然有用。

回答by jfs

Your time string is similar to the time format in rfc 2822 (date format in email, http headers). You could parse it using only stdlib:

您的时间字符串类似于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)

See solutions that yield timezone-aware datetime objects for various Python versions: parsing date with timezone from an email.

查看为各种 Python 版本生成时区感知日期时间对象的解决方案:parsing date with timezone from an email

In this format, ESTis semantically equivalent to -0500. Though, in general, a timezone abbreviation is not enough, to identify a timezone uniquely.

在这种格式中, EST在语义上等同于-0500. 但是,一般来说,时区缩写不足以唯一标识时区

回答by Christopher

Ran into this exact problem.

遇到了这个确切的问题。

What I ended up doing:

我最终做了什么:

# starting with date string
sdt = "20190901"
std_format = '%Y%m%d'

# create naive datetime object
from datetime import datetime
dt = datetime.strptime(sdt, sdt_format)

# extract the relevant date time items
dt_formatters = ['%Y','%m','%d']
dt_vals = tuple(map(lambda formatter: int(datetime.strftime(dt,formatter)), dt_formatters))

# set timezone
import pendulum
tz = pendulum.timezone('utc')

dt_tz = datetime(*dt_vals,tzinfo=tz)