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.074224b的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
相关产品推荐
相关产品推荐

