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

Posted

技术标签:

【中文标题】在 DST 更改发生时将字符串解析为日期【英文标题】:Parsing a string into date at the time the DST change happened 【发布时间】:2020-02-23 03:39:36 【问题描述】:

在西欧,2019-10-27 02:30:00 可能是“两个”时间事件:

凌晨 02:30 早于夏令时 03:00 更改 03:30 am,变成了(在 03:00 DST 更改之后)02:30 am

datetime parser 和 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 时间戳在欧洲/巴黎时区确实具有相同的日期时间)

【问题讨论】:

【参考方案1】:

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

is_dst 用于在歧义中确定正确的时区 夏令时结束时的时段。

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

使用 is_dst=None 来引发 AmbiguousTimeError 夏令时结束时的时间

如果 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 包来处理始终包含时区(默认为操作系统时区)的日期和时间。

参考文献

本地化方法的文档 - https://github.com/stub42/pytz/blob/master/src/pytz/tzinfo.py#L258

【讨论】:

感谢您的回答。这确实完全回答了这个评论。关于问题的第一部分,如何选择datetime.datetime.strptime("2019-10-27 02:30:00", '%Y-%m-%d %H:%M:%S')的答案?实际上可能是两个日期时间 添加了有关本地化的注释以涵盖该内容。 嘿,默认为英国英语。固定。

以上是关于在 DST 更改发生时将字符串解析为日期的主要内容,如果未能解决你的问题,请参考以下文章

将日期字符串解析为某个时区(支持夏令时)

java 字符串转换成日期

如何比较 DST 与 Laravel / Carbon 更改时的日期

在python中获取下一次DST更改的时间

如果日期是进行 DST(夏令时)更改的实际日期,有没有办法在 Python 中推断?

在 Swift 中,当方向发生时如何更改表格单元格布局?