这个问题在Python >= 3.9版本中得到了解决,标准库中的zoneinfo模块提供了解决方案。在Python >= 3.9版本中的解决方案可能是停止使用pytz。
In [1]: import datetime
In [2]: from zoneinfo import ZoneInfo
In [3]: start = datetime.datetime(2011, 6, 20, 0, 0, 0, 0, ZoneInfo('Asia/Kolkata'))
In [4]: print(start)
2011-06-20 00:00:00+05:30
这种极其令人困惑的行为的原因是,时区曾经没有标准化为:30或:00偏移量。在20世纪之交左右,大多数时区都采用了标准偏移量。在原帖的例子中,时区于1906年切换。对于美国/中央时区,这发生在1901年。
from datetime import datetime, timedelta, date
from pytz import timezone
d = datetime.combine(date.today(), time.min)
for tz in ('Asia/Kolkata', "US/Central"):
while d > datetime(1800, 1, 1):
localized = timezone(tz).localize(d)
if localized.isoformat()[-2:] not in ("00", "30"):
print(tz)
print(localized.isoformat())
print(timezone(tz).localize(d + timedelta(days=1)).isoformat())
break
d -= timedelta(days=1)
这将输出:
Asia/Kolkata
1906-01-01T00:00:00+05:21
1906-01-02T00:00:00+05:30
US/Central
1901-12-13T00:00:00-05:51
1901-12-14T00:00:00-06:00
Pytz似乎只在没有日期信息时使用最旧的偏移量,即使它很久以前就存在了。在一些非常自然的构造中,比如将tzinfo传递给datetime构造函数,时区对象并没有获得这些数据。
datetime
接口现在可以正常工作,这可以通过 Python 3.9 中引入的zoneinfo
模块 得到证明 - 它不需要localize
函数才能正常工作。 - Mark Ransom