为什么这些使用 pytz 的日期时间转换不会在 1901 年 12 月之前的几个小时登陆?

Why do these datetime conversions using pytz not land on hours before December of 1901?

提问人:Andrew Allaire 提问时间:10/13/2023 最后编辑:FObersteinerAndrew Allaire 更新时间:10/26/2023 访问量:98

问:

也许我没有正确使用图书馆,或者 1901 年 12 月 15 日发生了某种关于全球计时的标准更改。但是我在处理与时间相关的应用程序时偶然发现了这种奇怪的行为。

sydney = pytz.timezone("Australia/Sydney")
tokyo = pytz.timezone("Japan")
new_york = pytz.timezone("US/Eastern")

dt1 = datetime(1901, 12, 14)
dt2 = datetime(1901, 12, 15)

print("-" * 50)
print(sydney.localize(dt1).astimezone(pytz.UTC))
print(tokyo.localize(dt1).astimezone(pytz.UTC))
print(new_york.localize(dt1).astimezone(pytz.UTC))
print("-" * 50)
print(sydney.localize(dt2).astimezone(pytz.UTC))
print(tokyo.localize(dt2).astimezone(pytz.UTC))
print(new_york.localize(dt2).astimezone(pytz.UTC))
print("-" * 50)

我希望这段代码能告诉我这些不同时区的午夜时间的 UTC 等效值。我发现奇怪的是,对于 1901 年 12 月之前的旧日期,结果甚至没有落在小时上,而是有分钟成分。1901 年 12 月之后,似乎每一次转换都以整点结束。下面是上面代码的输出:

--------------------------------------------------
1901-12-13 13:55:00+00:00
1901-12-13 14:41:00+00:00
1901-12-14 05:00:00+00:00
--------------------------------------------------
1901-12-14 14:00:00+00:00
1901-12-14 15:00:00+00:00
1901-12-15 05:00:00+00:00
--------------------------------------------------

想知道我是否没有使用可靠的技术,或者由于某些历史/政治原因,这实际上是正确的?

Python 日期时间 时区 pytz

评论

0赞 Andrew Allaire 10/13/2023
请注意,对于 1901 年 12 月 13 日的纽约,它转换为凌晨 4:56 而不是凌晨 5:00。
2赞 stdunbar 10/13/2023
UTC 直到 1960 年才正式发布。众所周知,时区规则在世界范围内非常困难。查看 iana.org/time-zones 文件中的数据,因为存在大量的历史变化。我没有看到 1917 年之前澳大利亚的信息。您能解释一下您正在做的事情需要 120+ 年前的这种精确度吗?
0赞 mousetail 10/13/2023
对于很久以前,PTZ 使用该位置的实际时区到分钟,因为当时还没有时区
0赞 Andrew Allaire 10/13/2023
@stdunbar 在此应用程序中,我真的不需要处理 1990 年之前的时间。具体来说,转换与外汇交易时段的开始和结束时间有关。例如,悉尼时段在工作日当地早上 8 点开始,所以我想将其转换为 UTC,以便与全部以 UTC 为单位的市场数据进行比较,依此类推。所有市场数据都是1990年以后的数据。
2赞 slothrop 10/13/2023
看起来这里提出的 github.com/stub42/pytz/issues/77 同样的问题 - 尽管目前还不清楚过渡日期来自哪里。我对参考数据的天真阅读(一定是错误的)表明过渡应该发生在 1895 年:github.com/stub42/pytz/blob/......

答:

1赞 wjandrea 10/13/2023 #1

这似乎与 2038 年的问题有关,尽管我不确定具体如何。1901-12-13 20:45:52 UTC 比 Unix 纪元早几秒钟,如果我们看一下伦敦的那个时间,它比 Unix 纪元早了一分钟。2**31

import pytz
from datetime import datetime, timedelta

london = pytz.timezone("Europe/London")

dt0 = datetime(1901, 12, 13, 20, 45, 52)
second = timedelta(seconds=1)
for d in dt0-second, dt0, dt0+second:
    c = london.localize(d).astimezone(pytz.UTC)
    print(d, "|", c.time())
1901-12-13 20:45:51 | 20:46:51
1901-12-13 20:45:52 | 20:45:52
1901-12-13 20:45:53 | 20:45:53

顺便说一句,请注意,到 1901 年,这些示例都已经使用了基于 GMT 的标准时间。另一方面,例如,葡萄牙仅在 1912 年 1 月 1 日才采用它,因此没有表现出相同的行为。

评论

0赞 slothrop 10/13/2023
在 pytz 中肯定有一些 32 位 C ints 的用途:github.com/stub42/pytz/blob/......
2赞 FObersteiner 10/13/2023
为了支持您的假设:如果我使用 zoneinfo 时区运行您的代码,则输出符合预期。潜在地,“y2k38”问题可以追溯到 github.com/stub42/pytz/issues/31