mktime 导致溢出由于夏令时导致错误

mktime causing overflowError due to daylight savings time

提问人:stuartp 提问时间:10/6/2023 最后编辑:stuartp 更新时间:10/6/2023 访问量:47

问:

当夏令时设置为 true 时,我目前在以下代码上收到溢出错误。我尝试了许多日期/时间组合,似乎只有第 9 个参数(“is_dst”)设置为“1”,从而触发了问题。在 databricks 上测试的 python 版本为 3.8.10.final.0 和 3.10.12.final.0。

夏令时是否有任何特殊之处可能导致该问题 - 我不认为有关日期的任何内容都会导致溢出错误

import time
time.mktime(time.struct_time((2023, 10, 5, 12, 0, 0, 6, 68, -1)))
1696507200.0
time.mktime(time.struct_time((2023, 10, 5, 12, 0, 0, 6, 68, 0)))
1696507200.0
time.mktime(time.struct_time((2023, 10, 5, 12, 0, 0, 6, 68, 1)))
OverflowError: mktime argument out of range

更明确的版本

import pytz
from datetime import datetime, timezone

utc_dt = datetime.now(timezone.utc)  # UTC time
dt = utc_dt.astimezone()  # local time

btz = pytz.timezone("Australia/Brisbane") # currently +10
stz = pytz.timezone("Australia/Sydney") # currently +11

#brisbane
d1 = datetime.now(btz)
print(d1)
x1= d1.timetuple()
print(x1)
time.mktime(x1)
#sydney
d2 = datetime.now(stz)
print(d2)
x2= d2.timetuple()
print(x2)
time.mktime(x2)

输出为

2023-10-06 11:35:10.010458+10:00
time.struct_time(tm_year=2023, tm_mon=10, tm_mday=6, tm_hour=11, tm_min=35, tm_sec=10, tm_wday=4, tm_yday=279, tm_isdst=0)
2023-10-06 12:35:10.010884+11:00
time.struct_time(tm_year=2023, tm_mon=10, tm_mday=6, tm_hour=12, tm_min=35, tm_sec=10, tm_wday=4, tm_yday=279, tm_isdst=1)
OverflowError: mktime argument out of range

本周早些时候,当悉尼从AEST切换到AEDT(夏令时)时,这成为一个问题。服务器设置为此时区

蟒蛇 mktime

评论

0赞 Silvio Mayolo 10/6/2023
无法在 3.7.2 或 3.11.5 上重现。我在这两个版本中都没有例外。
0赞 blhsing 10/6/2023
@SilvioMayolo对底层平台进行系统调用,因此它与 Python 版本无关。mktime
0赞 eshirvana 10/6/2023
如前所述,调用底层库,它与平台相关。在我的本地计算机上运行此代码不会返回任何错误。mktime
0赞 stuartp 10/6/2023
我缩短了代码,试图显示错误的基础知识。我添加了更具表现力的代码,该代码显示了日期时间的生成和时区的指定 - 并且没有显式设置tm_isdt

答:

0赞 eshirvana 10/6/2023 #1

mktime调用底层 C 库,它与平台相关。

该参数用于指示夏令时 (DST) 在给定时间内是否有效。当 tm_isdst 设置为 1 时,表示 DST 已生效,这可能会导致函数出现问题,尤其是当它与系统的 DST 设置交互时。tm_isdsttime.mktime

为避免此问题,在创建struct_time时通常应避免将 tm_isdst 设置为 1。相反,让 Python 根据系统的设置自动处理 DST 信息。

评论

0赞 stuartp 10/9/2023
谢谢 - 很好的信息,但是根据上面编辑的代码 - 我没有明确将 tm_isdst 设置为 1 - 它是通过使用时区的 datetime.now(stz) 隐式设置的。STZ是悉尼时间(夏令时生效)。BTZ-布里斯班时间(夏令时无效)。使用 btz 工作时tm_isdst为 0,而 stz 则没有,因为tm_isdst是 1,您解释说这可能是一个问题 - 我想知道为什么这可能是一个问题,因为这似乎是它明确设置为处理的事情