mktime导致OverflowError: mktime参数超出范围

0 投票
1 回答
48 浏览
提问于 2025-04-14 16:26

在使用mktime获取时间时,我遇到了一个溢出异常。这种情况发生在Debian的docker镜像上,但在我的主机上却没有出现:

docker pull python:3.9.7

https://hub.docker.com/layers/library/python/3.9.7/images/sha256-9d7d2a6ce11fe5a12c74f81b860f5142fd91192427ece0b566c4fb962353325e?context=explore

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)

撰写回答