在 DST 更改发生时将字符串解析为日期

Parsing a string into date at the time the DST change happened

在西欧,2019-10-27 02:30:00 可能是 "two" 时间事件:

datetime 解析器和 pytz 如何处理解析此日期可能导致两个不同时间事件的事实?

import datetime, pytz
d = datetime.datetime.strptime("2019-10-27 02:30:00", '%Y-%m-%d %H:%M:%S')
d = pytz.timezone('Europe/Paris').localize(d)
print(d, d.timestamp())  

答案是2019-10-27 02:30:00+01:00 1572139800.0为什么不2019-10-27 02:30:00+02:00两者都可以。


备注:

import datetime
print(datetime.datetime.fromtimestamp(1572139800.0))  # 2019-10-27 02:30:00
print(datetime.datetime.fromtimestamp(1572136200.0))  # 2019-10-27 02:30:00

(这两个不同的 UTC 时间戳确实在 Europe/Paris 时区具有相同的日期时间)

方向由localize方法的is_dst参数决定。

is_dst is used to determine the correct timezone in the ambiguous period at the end of daylight saving time.

在问题的例子中,使用 True 会给你+02:00;和 False +01:00

Use is_dst=None to raise an AmbiguousTimeError for ambiguous times at the end of daylight saving time

如果 datetime 实例是原始的(或不包含时区),使用 localize 将应用时区,假设提供的实例是本地时间,并将偏移量应用到目标时区。

在使用 localize 之后,日期时间实例将不再简单,两个值将彼此相等,因为它们在技术上是同一时间。


这个问题突出了 datetime 模块的一个烦人的行为,除非明确指定 datetime 实例是天真的,这包括如果您的匹配表达式不包含时间则使用 strptime偏移量。

通过更改示例以包含可选的时区参数,事情变得更加清晰:

import pytz
from datetime import datetime

tz = pytz.timezone("Europe/Paris")
print(datetime.fromtimestamp(1572139800.0, tz))  # 2019-10-27 02:30:00+01:00
print(datetime.fromtimestamp(1572136200.0, tz))  # 2019-10-27 02:30:00+02:00

在包含时区的情况下,打印生成的 datetime 实例现在将包含偏移量以显示时间实际上并不相同。

我建议使用 arrow 包来处理日期和时间,它始终包含时区(默认为操作系统时区)。

参考资料