使用pytz时出现了奇怪的时区问题

59
>>> import pytz
>>> pytz.timezone('Asia/Hong_Kong')
<DstTzInfo 'Asia/Hong_Kong' LMT+7:37:00 STD>

七小时三十七分钟的偏移?这有点奇怪,有人遇到过同样的问题吗?

事实上,在以下两个时间之间,我获取到了不同的行为:

import pytz
from datetime import datetime
hk = pytz.timezone('Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
dt2 = hk.localize(datetime(2012,1,1))
if dt1 > dt2:
   print "Why?"

精确有什么问题吗?1885年1月1日13:00,当时的香港皇家天文台将香港时间首次设置为本地平均时间(GMT+7:36:41)。详见:http://en.wikipedia.org/wiki/Hong_Kong_Time#Time_standards - KurzedMetal
请查看以下链接:https://dev59.com/ZWgu5IYBdhLWcg3wRlL0#11442571 - Mark Ransom
1
可能是Python datetime对象显示错误的时区偏移的重复问题。 - congusbongus
3个回答

80

时区和偏移量会随着时间变化而改变。当 pytz 创建一个时区对象时,提供的默认区域名称和偏移量是该区域可用的最早的名称和偏移量,有时它们可能看起来有些奇怪。当您使用 localize 将时区附加到日期时,适当的区域名称和偏移量将被替换。如果仅使用 datetime 构造函数将时区附加到日期,则无法正确地调整。


17

虽然我确信时区的历史变化是一个因素,但即使对于自其创建以来未经历任何更改的时区,传递pytz时区对象到DateTime构造函数也会导致奇怪的行为。

import datetime
import pytz 

dt = datetime.datetime(2020, 7, 15, 0, 0, tzinfo= pytz.timezone('US/Eastern'))

生成

2020-07-15 00:00:00-04:56

创建datetime对象并将其本地化会产生预期的结果

import datetime
import pytz 

dt = datetime.datetime(2020, 7, 15, 0, 0)
dt_local = timezone('US/Eastern').localize(dt)

生成

2020-07-15 00:00:00-04:00

1
如果您查看Olson数据库中的示例数据,您会发现在1883年11月18日12:03:58之前,纽约的偏移量为4:56:02。因此,声称纽约时区从未更改是不正确的。 - Mark Ransom
3
虽然如此,但仍然可以合理地期望datetime将传递的时区对象与传递给其构造函数的数据参数相应地使用。 - rtphokie
在使用DateTime构造函数时需十分小心。请注意:使用t_now_secs = time.time()所得到的结果为-3600,即 float(datetime.datetime.fromtimestamp(t_now_secs, pytz.UTC).strftime('%s')) - t_now_secs。这是由于本地时间偏移量的影响导致的。 - Ytsen de Boer
@YtsendeBoer 是的,在您的示例中应用了本地偏移量,但它并不来自 tzinfo 实例。 - Mark Ransom
对于我们这些凡人来说,pytz的行为并不是人们所期望的。想象一下由此产生了多少微妙的时区错误存在于各个地方。 - KlausCPH
显示剩余4条评论

12

来到这里近10年后,我认为值得一提的是我们现在可以专门利用Python 3.9+标准库来处理时区,而无需使用“本地化陷阱”。

使用zoneinfo模块来设置和替换tzinfo,如下所示:

from datetime import datetime
from zoneinfo import ZoneInfo

hk = ZoneInfo('Asia/Hong_Kong')
print(repr(hk))
# zoneinfo.ZoneInfo(key='Asia/Hong_Kong')

dt1 = datetime(2012,1,1,tzinfo=hk)
print(dt1)
# 2012-01-01 00:00:00+08:00

如果无法使用zoneinfo,可以考虑以下替代方案:

pandas用户请注意:

  • pandas(v1.4.1)仍在内部使用pytz,并似乎存在一些问题与ZoneInfo时区对象一起使用

我认为datetimetzinfo之间的接口被扩展以使其能够工作。当创建pytz时,它被困在了原有的工作方式中。 - Mark Ransom
1
@MarkRansom没错,我记得我曾经在回答另一个问题时研究过这个。所以这不仅仅是添加一个库就可以完成的,而是需要一些进化。 - FObersteiner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接