gpt4 book ai didi

python - 将 timedelta 添加到本地日期时间,跨 DST 转换的意外行为

转载 作者:行者123 更新时间:2023-12-05 05:38:58 24 4
gpt4 key购买 nike

我刚刚在跨夏令时创建日期时间时偶然发现了 Python 日期时间的这种令人惊讶的行为。

将时间增量添加到本地日期时间可能不会增加我们预期的时间量。

import datetime as dt
from zoneinfo import ZoneInfo

# Midnight
d0 = dt.datetime(2020, 3, 29, 0, 0, tzinfo=ZoneInfo("Europe/Paris"))
# datetime.datetime(2020, 3, 29, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
d0.isoformat()
# '2020-03-29T00:00:00+01:00'

# Before DST shift
d1 = d0 + dt.timedelta(hours=2)
# datetime.datetime(2020, 3, 29, 2, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
d1.isoformat()
# '2020-03-29T02:00:00+01:00'

# After DST shift
d2 = d0 + dt.timedelta(hours=3)
# datetime.datetime(2020, 3, 29, 3, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))
d2.isoformat()
# '2020-03-29T03:00:00+02:00'

# Convert to UCT
d1u = d1.astimezone(dt.timezone.utc)
# datetime.datetime(2020, 3, 29, 1, 0, tzinfo=datetime.timezone.utc)
d2u = d2.astimezone(dt.timezone.utc)
# datetime.datetime(2020, 3, 29, 1, 0, tzinfo=datetime.timezone.utc)

# Compute timedeltas
d2 - d1
# datetime.timedelta(seconds=3600)
d2u - d1u
# datetime.timedelta(0)

我同意 d1 和 d2 相同,但 d2 不应该是“2020-03-29T04:00:00+02:00”吗?

d3 = d0 + dt.timedelta(hours=4)
# datetime.datetime(2020, 3, 29, 4, 0, tzinfo=zoneinfo.ZoneInfo(key='Europe/Paris'))

显然,当向本地日期时间添加时间增量(例如 3 小时)时,无论时区如何都会添加它,并且两个日期时间(实时/UTC)之间的增量不能保证是该时间增量(即由于 DST,可能需要 2 小时)。这有点陷阱。

原理是什么?这在某处记录了吗?

最佳答案

基本原理是:timedelta 算术是墙上时间算术。也就是说,它包括 DST 过渡时间(或不包括,具体取决于更改)。另见 P. Ganssle's blog post关于这个话题。

插图:

import datetime as dt
from zoneinfo import ZoneInfo

# Midnight
d0 = dt.datetime(2020, 3, 29, 0, 0, tzinfo=ZoneInfo("Europe/Paris"))

for h in range(1, 4):
print(h)
print(d0 + dt.timedelta(hours=h))
print((d0 + dt.timedelta(hours=h)).astimezone(ZoneInfo("UTC")), end="\n\n")
1
2020-03-29 01:00:00+01:00
2020-03-29 00:00:00+00:00 # as expected, 1 hour added

2
2020-03-29 02:00:00+01:00 # that's a non-existing datetime...
2020-03-29 01:00:00+00:00 # looks normal

3
2020-03-29 03:00:00+02:00
2020-03-29 01:00:00+00:00 # oops, 3 hours timedelta is only 2 hours actually!

需要更多的困惑吗?使用天真的日期时间。鉴于我的机器(欧洲/柏林)的 tz 具有与上面使用的 tz 相同的 DST 转换:

d0 = dt.datetime(2020, 3, 29, 0, 0)

for h in range(1, 4):
print(h)
print(d0 + dt.timedelta(hours=h))
print((d0 + dt.timedelta(hours=h)).astimezone(ZoneInfo("UTC")), end="\n\n")
1
2020-03-29 01:00:00 # 1 hour as expected
2020-03-29 00:00:00+00:00 # we're on UTC+1

2
2020-03-29 02:00:00 # ok 2 hours...
2020-03-29 00:00:00+00:00 # wait, what?!

3
2020-03-29 03:00:00
2020-03-29 01:00:00+00:00

关于python - 将 timedelta 添加到本地日期时间,跨 DST 转换的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72804395/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com