Python pytz 时区函数 returns 时差 9 分钟的时区
Python pytz timezone function returns a timezone that is off by 9 minutes
由于某些我还没有弄清楚的原因,从下面的代码:
>>> 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 分钟。
我已经查看了 source code for pytz
,但我承认我还没有完全弄清楚哪里出了问题。
我已将其他值传递给 timezone()
函数,它 returns 的值似乎是正确的。但出于某种原因,与我的时区相关的信息不正确。
最后,我隔壁办公室的同事确认 returns 函数在他的机器上提供了正确的时区信息。
有谁知道为什么我的时区 ('America/Chicago'
) 会偏移 9 分钟?我使用 pip
安装了 pytz
的 运行 版本 2015.7
。谢谢!
除非您当地的时区具有固定的 UTC 偏移量,否则在不提供具体 date/time.
的情况下谈论其具体值毫无意义
如果您提供时间,例如当前时间,那么您会看到 pytz
产生预期的 UTC 偏移量:
>>> from datetime import datetime
>>> import pytz
>>> datetime.now(pytz.timezone('America/Chicago')).strftime('%Z%z')
'CST-0600'
见
- Datetime Timezone conversion using pytz
- pytz localize vs datetime replace
如果您不提供特定的 date/time,则 pytz
可能 return 给定时区的可用 utc 偏移集的任意 utc 偏移。最近的 pytz
版本 return 对应于最早时间的 utc 偏移量(通常是 LMT),但你不应该依赖它。您和您的朋友可能使用了不同的 pytz 版本,这可能解释了结果的差异。
只是因为我的好奇心没有完全得到满足,所以最近我对这个问题进行了更多的研究。
最初,差异似乎源于 pytz
的不同版本。然而,在将我的 pytz
版本降级到我确认我得到的结果与我的机器上的结果不同的版本后,我发现这不是问题的根源:即使使用相同的版本pytz
我的机器似乎使用的是基于 LMT 的 UTC 偏移量,而其他机器使用的是基于 CDT 或 CST 的 UTC 偏移量。
根据我与@J.F.Sebastian 的谈话,我认为唯一可能的其他可能性是系统级别差异。我深入研究了 pytz
源代码,发现 pytz
从中获取至少部分时区信息的文件位于 /usr/share/zoneinfo/
中。所以我查看了文件 /usr/share/zoneinfo/America/Chicago
,虽然它是一个二进制文件,但它的一部分是可读的。在文件的中途有一个时区列表:LMTCDTCSTESTCWTCPT
。如您所见,LMT
是列表中的第一个名字,正如@J.F.Sebastian 所建议的那样,这似乎是 pytz
在我最初的问题中描述的情况中使用的名字。
这就是 Ubuntu 15.10 中列表的样子。但是,在我得到结果 -600 而不是 -609 结果的 Ubuntu(例如,Trusty 和 Precise)的早期版本中,相同的列表是 CDTCSTESTCWTCPT
.
我承认这是由于大量的盲目探索和半知半解,但似乎这就是我在不同机器上看到的差异的原因。至于为什么 zoneinfo
文件在不同版本中不同,以及这些差异对 Ubuntu 意味着什么,我不知道,但我想我会与那些同样好奇的人分享我的发现,并可能从社区接收有见地的 corrections/supplemental 信息。
正如您提到的,原始文件与 pytz 模块存在一些差异:(在我的例子中使用中部时间)
xxxx......lib/python2.7/site-packages/pytz/zoneinfo/US/Central
In [66]: start = start.replace(tzinfo=central)
In [67]: start.isoformat()
Out[67]: '2018-02-26T00:00:00-05:51'
如果你使用OS的标准文件(我在mac、ubuntu和centos测试过)
/usr/share/zoneinfo/US/Central
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'
答案基于 Carl Meyer 在 Google Groups Answer
中的回答
造成这种差异的原因是,这不是将时区不可知的日期时间对象转换为时区感知对象的正确方法。
解释为:
"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 组中引用的答案)
基本上,你应该这样做:
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
由于某些我还没有弄清楚的原因,从下面的代码:
>>> 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 分钟。
我已经查看了 source code for pytz
,但我承认我还没有完全弄清楚哪里出了问题。
我已将其他值传递给 timezone()
函数,它 returns 的值似乎是正确的。但出于某种原因,与我的时区相关的信息不正确。
最后,我隔壁办公室的同事确认 returns 函数在他的机器上提供了正确的时区信息。
有谁知道为什么我的时区 ('America/Chicago'
) 会偏移 9 分钟?我使用 pip
安装了 pytz
的 运行 版本 2015.7
。谢谢!
除非您当地的时区具有固定的 UTC 偏移量,否则在不提供具体 date/time.
的情况下谈论其具体值毫无意义如果您提供时间,例如当前时间,那么您会看到 pytz
产生预期的 UTC 偏移量:
>>> from datetime import datetime
>>> import pytz
>>> datetime.now(pytz.timezone('America/Chicago')).strftime('%Z%z')
'CST-0600'
见
- Datetime Timezone conversion using pytz
- pytz localize vs datetime replace
如果您不提供特定的 date/time,则 pytz
可能 return 给定时区的可用 utc 偏移集的任意 utc 偏移。最近的 pytz
版本 return 对应于最早时间的 utc 偏移量(通常是 LMT),但你不应该依赖它。您和您的朋友可能使用了不同的 pytz 版本,这可能解释了结果的差异。
只是因为我的好奇心没有完全得到满足,所以最近我对这个问题进行了更多的研究。
最初,差异似乎源于 pytz
的不同版本。然而,在将我的 pytz
版本降级到我确认我得到的结果与我的机器上的结果不同的版本后,我发现这不是问题的根源:即使使用相同的版本pytz
我的机器似乎使用的是基于 LMT 的 UTC 偏移量,而其他机器使用的是基于 CDT 或 CST 的 UTC 偏移量。
根据我与@J.F.Sebastian 的谈话,我认为唯一可能的其他可能性是系统级别差异。我深入研究了 pytz
源代码,发现 pytz
从中获取至少部分时区信息的文件位于 /usr/share/zoneinfo/
中。所以我查看了文件 /usr/share/zoneinfo/America/Chicago
,虽然它是一个二进制文件,但它的一部分是可读的。在文件的中途有一个时区列表:LMTCDTCSTESTCWTCPT
。如您所见,LMT
是列表中的第一个名字,正如@J.F.Sebastian 所建议的那样,这似乎是 pytz
在我最初的问题中描述的情况中使用的名字。
这就是 Ubuntu 15.10 中列表的样子。但是,在我得到结果 -600 而不是 -609 结果的 Ubuntu(例如,Trusty 和 Precise)的早期版本中,相同的列表是 CDTCSTESTCWTCPT
.
我承认这是由于大量的盲目探索和半知半解,但似乎这就是我在不同机器上看到的差异的原因。至于为什么 zoneinfo
文件在不同版本中不同,以及这些差异对 Ubuntu 意味着什么,我不知道,但我想我会与那些同样好奇的人分享我的发现,并可能从社区接收有见地的 corrections/supplemental 信息。
正如您提到的,原始文件与 pytz 模块存在一些差异:(在我的例子中使用中部时间)
xxxx......lib/python2.7/site-packages/pytz/zoneinfo/US/Central
In [66]: start = start.replace(tzinfo=central)
In [67]: start.isoformat()
Out[67]: '2018-02-26T00:00:00-05:51'
如果你使用OS的标准文件(我在mac、ubuntu和centos测试过)
/usr/share/zoneinfo/US/Central
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'
答案基于 Carl Meyer 在 Google Groups Answer
中的回答造成这种差异的原因是,这不是将时区不可知的日期时间对象转换为时区感知对象的正确方法。
解释为:
"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 组中引用的答案)
基本上,你应该这样做:
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