问题 Python pytz timezone函数返回一个关闭9分钟的时区


由于某些我无法弄清楚的原因,从以下代码:

>>> from pytz import timezone
>>> timezone('America/Chicago')

我明白了:

<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD>

什么时候,我认为,我应该得到:

<DstTzInfo 'America/Chicago' LMT-1 day, 18:00:00 STD>

...因为我认为我的时区距离UTC不到6小时9分钟。

我看过了 的源代码 pytz 但我承认我还没弄清楚出了什么问题。

我已将其他值传递给了 timezone() 函数,它返回的值似乎是正确的。但出于某种原因,与我的时区相关的信息不正确。

最后,我旁边的立方体中的同事确认该函数在他的机器上返回正确的时区信息。

有谁知道为什么我的时区('America/Chicago')将在9分钟后关闭?我正在运行版本 2015.7 的 pytz 安装使用 pip。谢谢!


8002
2018-02-17 16:53


起源

你得到当地的平均时间 stackoverflow.com/questions/11473721/...  tz= timezone('America/Chicago'); tz.localize(datetime.datetime.now()) - Padraic Cunningham
@PadraicCunningham绝对看起来像我正在经历的。知道为什么我旁边的人的机器上的相同代码会得到不同的结果吗? - elethan
我还建议你的朋友更新你不要降级 - Padraic Cunningham
@PadraicCunningham:不要用 tz.localize(datetime.now());使用 datetime.now(tz) 代替。前者可能在DST过渡期间失败。 - jfs
@PadraicCunningham:想想为什么 localize() 具有 is_dst 参数。想想为什么你现在不需要它(.now(tz))。这个讨论不适合当前的问题。看到 怎么问 - jfs


答案:


除非您的本地时区具有固定的UTC偏移量,否则在没有提供特定日期/时间的情况下讨论其特定值是没有意义的。

如果您提供时间,例如当前时间,那么您将看到 pytz 产生预期的UTC偏移量:

>>> from datetime import datetime
>>> import pytz
>>> datetime.now(pytz.timezone('America/Chicago')).strftime('%Z%z')
'CST-0600'

看到

如果您没有提供具体的日期/时间 pytz 可以从给定时区的可用utc偏移集返回任意utc偏移量。最近 pytz 版本返回与最早时间(LMT作为规则)相对应的utc偏移量,但您不应该依赖它。您和您的朋友可能会使用不同的pytz版本来解释结果的差异。


3
2018-02-17 18:36



在我弄清楚如何降级到我的同事版本之前,我认为这个解决方案可以正常工作并将其标记为正确 pytz。现在我拥有与他完全相同的版本,但是从交互式提示中,我们得到了与调用不同的结果 pytz.timezone('America/Chicago') (即,我明白了 18:09:00, 他得到 18:00:00。如果它不是,那么还有什么可以解释这种差异的原因 pytz 版?它可能是系统级配置的差异吗? - elethan
@elethan:答案中的代码有效。它必须生产 'CST-0600' 否则你的安装就坏了。请注意答案中的“无意义”,“不应该依赖” - 您必须提供日期/时间,例如,如答案中的示例代码所示。 - jfs
你的答案中的代码确实有效。我的问题是打电话 pytz.timezone('America/Chicago') 总是回来 <DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD> 在我的机器上,总是返回 <DstTzInfo 'America/Chicago' LMT-1 day, 18:00:00 STD> 在我测试过的其他机器上(即使使用相同版本的 pytz)我最初的问题是询问差异的原因。我从你的答案中假设它是由版本的差异引起的,但似乎并非如此。 - elethan
1-此值(没有特定时间的UTC偏离tz)是没有意义的。你明白那部分吗? 2-这个值取决于pytz版本。它可能也取决于其他事情,但我的猜测是你已经使用错误的pytz版本进行了测试。无论如何都没关系。在没有提供时间的情况下(如果时区具有非固定的UTC偏移量,例如America / Chicago),您永远不应该依赖显示的UTC偏移量。如果你提供时间;你应该在不同的平台上获得相同的值(给定相同的tz数据库版本)。 - jfs
我理解所有这一切,我同意你的看法。如果你可能知道什么可以解释相同版本的差异,我只是很好奇 pytz。显然,如果您不选择给定特定时间,则pytz不会随机选择偏移量,因为结果是一致的(即使选择方法可能随版本而变化)。我想知道为什么它在不同的机器上选择不同的偏移量。 - elethan


仅仅因为我的好奇心并不完全令人满意,我最近又对这个问题进行了一些研究。

最初,似乎差异源于不同版本的 pytz。但是,在降级我的版本之后 pytz 在我确认我的机器上有不同结果的版本中,我发现这不是问题的根源:即使使用相同版本的 pytz 我的机器似乎使用基于LMT的UTC偏移,而其他机器使用基于CDT或CST的一个。

根据我与@ J.F.Sebastian的对话,我认为唯一可能的另一种可能性是系统级差异。我挖了进去 pytz 源代码多了一点,发现文件在哪里 pytz 从中得到至少一些时区信息 /usr/share/zoneinfo/。所以我查看了该文件 /usr/share/zoneinfo/America/Chicago 虽然它是一个二进制文件,但它的一部分是可读的。在文件的中间有一个时区列表: LMTCDTCSTESTCWTCPT。如你看到的, LMT 是列表中的第一个名字,正如@ J.F.Sebastian建议的那样,taht似乎是那个 pytz 用于我原始问题中描述的情况。

这就是Ubuntu 15.10中列表的样子。但是,在早期版本的Ubuntu(例如,Trusty和Precise)中,我得到结果-600而不是-609结果,同样的列表是 CDTCSTESTCWTCPT

我承认这是来自盲目探索和半理解,但似乎这是我在机器上看到的差异的原因。至于为什么 zoneinfo 各个版本的文件不同,这些差异对Ubuntu意味着什么,我不知道,但我想我会为那些同样好奇的人分享我的发现,并可能从社区获得有见地的更正/补充信息。


3
2018-03-03 17:52



注意:股票 pytz 使用捆绑 zoneinfo (子目录)。如果你看到了 /usr/share/zoneinfo 用来;这意味着你使用了修改过的 pytz 包(例如,如果您已安装 pytz 运用 sudo apt-get python-tz 然后 pytz 使用 open_resource() 在Debian中修补,使用tzdata包中的系统zoneinfo)。如果库存和修补版本具有相同的功能,则会很糟糕 __version__, pytz.OLSON_VERSION 但是你不应该对它们产生不同结果感到惊讶(修补版本可能就是OLSON_VERSION,即系统可能使用较新的tzdata版本)。 - jfs


根据Carl Meyer的答案回答 Google网上论坛答案

造成这种差异的原因是,这不是将时区无关的日期时间对象转换为时区感知对象的正确方法。

解释是:

“pytz时区类不代表UTC的单一偏移量,它   代表一个在历史进程中具有的地理区域   可能经历了几种不同的UTC偏移。最古老的偏移   对于给定区域,表示时区之前的偏移量   标准化(在19世纪后期,大多数地方)通常被称为“LMT”   (本地平均时间),它经常偏离UTC一个奇数   分钟。”

(引自Google网上论坛中引用的答案)

基本上,你应该这样做:

from datetime import datetime
import pytz

my_datetime = datetime(2015, 6, 11, 13, 30)
my_tz = pytz.timezone('America/Chicago')    
good_dt = my_tz.localize(my_datetime)

print(good_dt)

out: 2015-06-11 13:30:00-05:00


3
2018-05-30 20:47





正如您所提到的,原始文件与pytz模块存在一些差异:(在我的情况下使用Central时间)

XXXX ...... LIB / python2.7 /站点包/ pytz / zoneinfo中/美/中环

In [66]: start = start.replace(tzinfo=central)

In [67]: start.isoformat()
Out[67]: '2018-02-26T00:00:00-05:51'

如果您使用操作系统的标准文件(我在mac,ubuntu和centos中测试过)

在/ usr / share / zoneinfo中/美/中环

mv xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central-bak

ln -s /usr/share/zoneinfo/US/Central xxxx...../lib/python2.7/site-packages/pytz/zoneinfo/US/Central

问题得到解决

In [7]: central = timezone('US/Central')

In [8]: central
Out[8]: <DstTzInfo 'US/Central' CST-1 day, 18:00:00 STD>

In [10]: start = start.replace(tzinfo=central)

In [11]: start.isoformat()
Out[11]: '2018-02-27T00:00:00-06:00'


0
2018-02-27 22:11