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

Python使用pytz时带时区datetime比较结果异常排查

问题根源

这个错误完全是pytz的使用方式不对导致的:绝对不要直接把pytz生成的时区对象传给datetime构造/combine方法的tzinfo参数。
pytz的时区对象存了对应地区从有时间记录以来所有历史阶段的UTC偏移规则,其中最早的一条就是本地平均时间(LMT)——纽约的LMT偏移恰好是-04:56,是1883年美国统一标准时间之前纽约当地用的时间,和现在用的夏令时EDT(-04:00)、冬令时EST(-05:00)完全不是一回事。
当你直接给tzinfo传pytz时区对象时,Python不会自动根据你传入的年月日时分去匹配对应时段的正确偏移,只会默认取这个时区存的最早的LMT规则,这就是你看到b的偏移是-04:56、tzinfo显示LMT的原因。
而你生成a的时候用的是datetime.datetime.now(est_tz),这个方法在传入pytz时区时,会自动触发pytz的偏移匹配逻辑,给a绑定上当前时间对应的正确EDT偏移,所以a的tzinfo是正常的。
两个时间比大小时会先转成UTC时间计算:

  • a的UTC时间是2022-06-08 20:33:39.074224
  • b的UTC时间是2022-06-08 20:56:00
    算下来b的时间反而比a晚22分钟左右,自然会输出a < b为True的反常结果。
修复方案

用pytz的时候,正确的时区绑定方式是先生成不带时区的朴素时间对象,再调用pytz时区的localize()方法完成绑定,这个方法会自动根据时间值匹配对应时段的正确偏移:

import datetime
import pytz

est_tz = pytz.timezone("America/New_York")
a = datetime.datetime.now(est_tz)
# 先拼出不带时区的整点时间
naive_b = datetime.datetime.combine(
    a.date(),
    datetime.time(hour=a.hour, minute=0)
)
# 用localize绑定时区,自动匹配正确偏移
b = est_tz.localize(naive_b)

print(a)
print(b)
print(a < b)  # 输出False,符合a > b的预期

运行结果完全符合预期:

2022-06-08 16:33:39.074224-04:00
2022-06-08 16:00:00-04:00
False
补充

如果你的Python版本是3.9及以上,完全可以抛弃pytz,用标准库自带的zoneinfo模块处理时区,这个模块不存在pytz的这个坑,时区对象可以直接传给tzinfo参数,会自动匹配正确偏移:

import datetime
from zoneinfo import ZoneInfo

est_tz = ZoneInfo("America/New_York")
a = datetime.datetime.now(est_tz)
b = datetime.datetime.combine(
    a.date(),
    datetime.time(hour=a.hour, minute=0),
    tzinfo=est_tz
)
print(a < b) # 直接输出False,不需要额外的localize步骤

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 07:12:52