You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python(pytz)中以支持DST的方式为datetime添加一天?

在US/Eastern时区夏令时转换时正确实现日期日增迭代器

在处理US/Eastern时区的日期迭代时,遇到夏令时(DST)转换边界(2024年11月3日到4日)会出现问题:当地时间11月3日0点到11月5日0点间隔25小时,直接用datetime.timedelta(days=1)加24小时会得到不符合预期的结果,无法正确跳到下一天的当地时间。

比如原代码的问题:

import datetime  
import pytz  
ET = pytz.timezone("US/Eastern")  
first_day = ET.localize(datetime.datetime(2024, 11, 3))  
next_day = first_day + datetime.timedelta(days=1)  

first_day.isoformat()  # '2024-11-03T00:00:00-04:00'  
next_day.isoformat()  # '2024-11-04T00:00:00-04:00'  

assert next_day == ET.localize(datetime.datetime(2024, 11, 4))  # 断言失败

使用ET.normalize(next_day)得到的是'2024-11-03T23:00:00-05:00',也不符合预期。


核心原因

timedelta(days=1)是按绝对时间增加24小时,但在DST结束时,US/Eastern时区的偏移从-04:00(EDT)切换到-05:00(EST),导致当地日历日的绝对时长变为25小时。直接加24小时只会走到下一日历日的前一小时,而非我们需要的“下一个日历日的同一当地时间”。


解决方案

方案1:基于日历日期递增(pytz兼容)

直接操作date对象而非带时区的datetime的绝对时间,先取当前日期加一天,再重新构造成带时区的datetime:

import datetime
import pytz

ET = pytz.timezone("US/Eastern")
first_day = ET.localize(datetime.datetime(2024, 11, 3))

# 提取日期部分,加一天后重新本地化
next_calendar_date = first_day.date() + datetime.timedelta(days=1)
next_day = ET.localize(datetime.datetime.combine(next_calendar_date, datetime.time.min))

print(first_day.isoformat())  # '2024-11-03T00:00:00-04:00'
print(next_day.isoformat())   # '2024-11-04T00:00:00-05:00'
assert next_day == ET.localize(datetime.datetime(2024, 11, 4))  # 断言通过

方案2:使用Python3.9+自带的zoneinfo(推荐)

zoneinfo是Python标准库的一部分,处理时区更直观,无需额外安装:

from zoneinfo import ZoneInfo
import datetime

ET = ZoneInfo("US/Eastern")
first_day = datetime.datetime(2024, 11, 3, tzinfo=ET)

# 同样基于日历日期递增
next_calendar_date = first_day.date() + datetime.timedelta(days=1)
next_day = datetime.datetime.combine(next_calendar_date, datetime.time.min, tzinfo=ET)

print(first_day.isoformat())  # '2024-11-03T00:00:00-04:00'
print(next_day.isoformat())   # '2024-11-04T00:00:00-05:00'
assert next_day == datetime.datetime(2024, 11, 4, tzinfo=ET)  # 断言通过

迭代器实现

如果要封装成循环迭代器,可以这样写:

from zoneinfo import ZoneInfo
import datetime

def date_iterator(start_date, timezone, days=1):
    current = datetime.datetime.combine(start_date, datetime.time.min, tzinfo=timezone)
    while True:
        yield current
        current_date = current.date() + datetime.timedelta(days=days)
        current = datetime.datetime.combine(current_date, datetime.time.min, tzinfo=timezone)

# 使用示例
ET = ZoneInfo("US/Eastern")
start = datetime.date(2024, 11, 2)
iterator = date_iterator(start, ET)

# 迭代前3天
for _ in range(3):
    day = next(iterator)
    print(day.isoformat())
# 输出:
# 2024-11-02T00:00:00-04:00
# 2024-11-03T00:00:00-04:00
# 2024-11-04T00:00:00-05:00

内容的提问来源于stack exchange,提问作者Pwnosaurus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 10:24:51