Python pytz时区函数返回一个9分钟的时区

Python pytz timezone function returns a timezone that is off by 9 minutes

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

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

我明白了:

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

我想,我应该得到:

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

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

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

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

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

有没有人知道为什么我的时区('America/Chicago')会在9分钟后关闭? 我正在使用pip运行pytz2015.7版本。 谢谢!


根据Carl Meyer在Google网上论坛答案中的回答做出回答

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

解释是:

"A pytz timezone class does not represent a single offset from UTC, it
represents a geographical area which, over the course of history, has
probably gone through several different UTC offsets. The oldest offset
for a given zone, representing the offset from before time zones were
standardized (in the late 1800s, most places) is usually called"LMT"
(Local Mean Time), and it is often offset from UTC by an odd number of
minutes."

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

基本上,你应该这样做:

1
2
3
4
5
6
7
8
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


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

最初,似乎差异源于不同版本的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意味着什么,我不知道,但我想我会为那些同样好奇的人分享我的发现,并可能获得深刻见解的修正/补充信息来自社区。


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

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

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

看到

  • 使用pytz的Datetime时区转换
  • pytz localize vs datetime replace

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


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

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

1
2
3
4
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中/美/中环

1
2
3
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

问题得到解决

1
2
3
4
5
6
7
8
9
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'