mktime导致OverflowError: mktime参数超出范围
在使用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日的上周,它就能正常工作,没有抛出异常。
1 个回答
1
我发现了为什么改变日期能解决这个问题的原因。在北美,我们有一个夏令时的规定,从2024年3月10日开始生效。这就是为什么在3月10日之前设置系统时间时,一切都正常。但在夏令时生效后,就会出现异常。
在 timetuple() 这个函数中,有一个叫做 is_dst 的字段,只有在夏令时生效时才会添加。当你把这个字段传给 mktime 函数时,在一些旧的 Linux 系统上(比如问题中提到的 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)