尝试使用 mktime 获取时间时,出现溢出异常。这发生在 Debian docker 映像上,但不会发生在我的主机上:
docker pull python:3.9.7
pytz==2021.3
这是一个玩具示例:
import datetime
import time
import pytz
ts = 1655043357
tz = 'Canada/Eastern'
utc_time = datetime.datetime.now(tz=pytz.utc)
tz = pytz.timezone(tz)
tz_aware = datetime.datetime.now(tz=tz)
utc_ts = time.mktime(utc_time.timetuple()) # No exception
ts = time.mktime(tz_aware.timetuple()) # <----Results in exception
例外:
Traceback (most recent call last):
File "/home/toy_example.py", line 15, in <module>
time.mktime(tz_aware.timetuple())
OverflowError: mktime argument out of range
在我的主机上运行时没有任何异常并且按预期工作。知道为什么会这样吗?
编辑: 有趣的是,如果我将当前系统时间更改为上周 2024 年 3 月 7 日,它可以正常工作,不会引发异常
找出更改日期修复异常的原因。我们北美地区的夏令时于 2024 年 3 月 10 日生效。这就是为什么在 3 月 10 日之前设置系统时间时一切正常。夏令时生效后,异常开始发生。
作为 timetuple() 的一部分,有一个 is_dst 字段,仅在夏令时生效时添加。当您将其传递到旧版 Linux 平台中的 mktime 时(例如问题中的 docker 映像),它将触发(非常误导性的)溢出异常。在较新的平台上,它接受 is_dst (适用于较新的 debian 和 osx)。
正确的方法是完全避免 mktime:
# current date and time
tz = 'Canada/Eastern'
tz = pytz.timezone(tz)
tz_aware = datetime.now(tz=tz)
ts = datetime.timestamp(tz_aware)
utc_time = datetime.datetime.now(tz=pytz.utc)
utc_ts = datetime.timestamp(utc_time)