如何使用dateutil.tz.tz.tzoffset本地化使用strptime创建的时区原始日期时间?

时间:2019-05-16 17:49:58

标签: python datetime pytz python-dateutil

如何使用类型为dateutil.tz.tz.tzoffset的对象本地化具有正确时区和DST信息的时区朴素datetime对象,以便可以将其正确转换为UTC?另外,如何将dateutil.tz.tz.tzoffset转换为pytz.timezone?

我无法找到有关使用dateutil.tz.tz.tzoffset对象定位datetime对象的良好信息。请参阅下面的一些我已阅读的更好的文章。

背景信息:

我正在处理许多日期字符串,其中大多数没有时区信息。在某些情况下,时间是格林尼治标准时间(GMT),在其他情况下则是当地时间。我必须首先确定创建这些各种日志的设备的时区,然后解析各种日期字符串,如果是本地时间,则添加添加时区,最后将其转换为UTC。

我几乎可以完成所有工作,除了唯一可靠的方法来确定TimeZone是从文本文件中确定的,该文本文件的日期为EDT,IST等格式,因此我在下面使用了投票最多的帖子链接使用dateutil的parser.parse()函数完成此任务,并为其发送tzinfos参数的字典。 (Parsing date/time string with timezone abbreviated name in Python?

但是,这给我留下了一个DateTime,它具有tzinfo type = dateutil.tz.tz.tzoffset。我可以,除非我需要使用此tzinfo来本地化不包含时区信息的字符串,并且dateutil.tz.tz.tzoffset类型没有像pytz.timezone那样的本地化选项,这才是关键我的问题。

我把这个变得太难了吗?我只是用保存的dateutil.tz.tz.tzoffset对象替换时区朴素datetime中的tzinfo吗?

代码:

以下读取日期字符串并将其保存为datetime对象,将时区保存在var中供以后使用,然后将日期字符串转换为UTC:

from dateutil.parser import parse as parsedate
import pytz
from pytz import timezone
from datetime import datetime

timestr = 'Sat, 5/01/2019 8:00PM EDT' #only reliable source of timezone info
dtfromstrEDT = parsedate(timestr, tzinfos=tzd) #tzd is created from the above link
mytimeZone = dtfromstrEDT.tzinfo  # save local timezone
dtUTC = dtfromstrEDT.astimezone(pytz.timezone('UTC'))  # convert to utc

现在这是一个新的时区天真日期字符串。它是在与上述(EDT)相同的本地时间记录的,因此我想使用保存的mytimeZone var对其进行本地化并转换为UTC。我使用标准的strptime将其作为原始日期时间读取。但是,当使用mytimeZone本地化朴素日期时间时,它将失败。错误如下。我了解错误;但我不知道该如何满足我的需求:

timestrnaive = 'Mar 15 12:09:20 2019' #in EDT time, same as above string but without any timezone info
dtfromstrNaive = datetime.strptime(timestrnaive, "%b %d %H:%M:%S %Y")
dtlocalized = mytimeZone.localize(dtfromstrNaive, is_dst=True)  
# the above is where it fails with provided error below
# however I can do this instead if I had a pytz.timezone object:
loc_tz = pytz.timezone('America/New_York')
dtlocalized = loc_tz.localize(dtfromstrNaive, is_dst=True) 
dtUTC2 = dtlocalized.astimezone(pytz.timezone('UTC'))  # convert to utc

错误:

Traceback (most recent call last):
  File "C:\Examples\timezones.py", line 221, in <module>
    dtlocalized = mytimeZone.localize(dtfromstrNaive, is_dst=True)  # convert to whatever tz is stored in self.timeZone
AttributeError: 'tzoffset' object has no attribute 'localize'

评论了以下内容:

Localize datetime (timezone aware) from timezone offset-我不确定如何将其应用于此问题,因为我有dateutil.tz.tz.tzoffset对象,而不是原始utc时间。

Parsing date/time string with timezone abbreviated name in Python?-这使我可以读取时区数据,例如EDT和PDT。

How to make an unaware datetime timezone aware in python-这无济于事,因为它不能解决我提到的dateutil.tz.tz.tzoffset问题。

2 个答案:

答案 0 :(得分:1)

您在这里存在的主要误解是您需要localize方法,这是pytz的历史产物,它是从PEP 495添加“ fold”属性之前的时代开始的。您可以在this article中详细了解pytz偏离标准库界面的原因。

正如您在答案中指出的那样,对于除pytz区域以外的任何 区域,您可以简单地使用.replace来构建具有适当时区的新日期时间。还有一个dateutil.utils.default_tzinfo便利功能,它将自动检测日期时间是否为天真,并且将默认值附加到tzinfo

要注意的另一件事是,这里不需要使用pytz,因为dateutil还提供了UTC对象,因此您可以执行以下操作:

from dateutil import tz
timestrnaive = 'Mar 15 12:09:20 2019'
dtfromstrNaive = datetime.strptime(timestrnaive, "%b %d %H:%M:%S %Y") 
dtlocalized = dtfromstrNaive.replace(tzinfo=mytimeZone)
dtUTC2 = dtlocalized.astimezone(tz.UTC) # Convert to UTC

因此,您无需保留对pytz的任何依赖。

如果您想了解有关在Python中使用时区的更多信息,我也recently gave a talk about this at PyCon

答案 1 :(得分:0)

经过更多测试后,我意识到我已经很难做到这一点。解决方案很简单:

timestrnaive = 'Mar 15 12:09:20 2019'
dtfromstrNaive = datetime.strptime(timestrnaive, "%b %d %H:%M:%S %Y") 
dtlocalized = dtfromstrNaive.replace(tzinfo=mytimeZone)
dtUTC2 = dtlocalized.astimezone(pytz.timezone('UTC'))  # convert to utc