`timedelta` 对象不考虑夏令时
`timedelta` object not accounting for daylight savings
我正在尝试获取适当的时间范围以在用户本地时区的数据库中查询(其中日期时间以 UTC 格式存储)。这是我发现的一些我不知道如何解决的奇怪行为:
import pytz
from datetime import datetime, timedelta
local_tz = pytz.timezone("America/New_York")
utc = pytz.timezone("UTC")
start = local_tz.localize(datetime(2019, 11, 3)) # 2019-11-03 00:00:00-04:00
end = start + timedelta(days=1) # 2019-11-04 00:00:00-04:00
start_utc = utc.normalize(start) # 2019-11-03 04:00:00+00:00
end_utc = utc.normalize(end) # 2019-11-04 04:00:00+00:00
utc.normalize(local_tz.localize(datetime(2019, 11, 4))) # 2019-11-04 05:00:00+00:00
通过将 timedelta
对象添加到 start
来规范化 end
变量时,夏令时更改会以某种方式丢失。为什么会这样?
不确定日期时间计算的预期行为,但我将仅解释共享代码示例中的行为。
pytz.localize
创建一个时区感知日期时间实例。当纽约时区用于 localize
原始日期时间时,它会分配正确的时区,EDT
直到 11 月 3 日,EST
为 11 月 4 日及以后。让我们在这里排除 timedelta
:
>>> import pytz
>>> from datetime import datetime, timedelta
>>> tz_ny = pytz.timezone("America/New_York")
>>> tz_ny.localize(datetime(2019, 11, 3))
datetime.datetime(2019, 11, 3, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
>>> tz_ny.localize(datetime(2019, 11, 4))
datetime.datetime(2019, 11, 4, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
正如所见,DstTzInfo
与预期不同,因为纽约夏令时在 11 月 3 日结束。
共享代码示例在 localizing
11 月 3 日之前创建了 start
,它将 EDT
作为 tzinfo
分配给日期时间对象(使用夏令时)。要创建end
,1天的timedelta
被添加到start
,但是datetime
对象的tzinfo
是kept untouched:
>>> start = tz_ny.localize(datetime(2019, 11, 3))
>>> start.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>
>>> end = start + timedelta(days=1)
>>> end.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>
因此 end
是 11 月 4 日的 datetime
,但 DstTzInfo
信息仍与 11 月 3 日相同。这不同于 localizing
11 月 4 日的天真 datetime
,它不使用夏令时。
我正在尝试获取适当的时间范围以在用户本地时区的数据库中查询(其中日期时间以 UTC 格式存储)。这是我发现的一些我不知道如何解决的奇怪行为:
import pytz
from datetime import datetime, timedelta
local_tz = pytz.timezone("America/New_York")
utc = pytz.timezone("UTC")
start = local_tz.localize(datetime(2019, 11, 3)) # 2019-11-03 00:00:00-04:00
end = start + timedelta(days=1) # 2019-11-04 00:00:00-04:00
start_utc = utc.normalize(start) # 2019-11-03 04:00:00+00:00
end_utc = utc.normalize(end) # 2019-11-04 04:00:00+00:00
utc.normalize(local_tz.localize(datetime(2019, 11, 4))) # 2019-11-04 05:00:00+00:00
通过将 timedelta
对象添加到 start
来规范化 end
变量时,夏令时更改会以某种方式丢失。为什么会这样?
不确定日期时间计算的预期行为,但我将仅解释共享代码示例中的行为。
pytz.localize
创建一个时区感知日期时间实例。当纽约时区用于 localize
原始日期时间时,它会分配正确的时区,EDT
直到 11 月 3 日,EST
为 11 月 4 日及以后。让我们在这里排除 timedelta
:
>>> import pytz
>>> from datetime import datetime, timedelta
>>> tz_ny = pytz.timezone("America/New_York")
>>> tz_ny.localize(datetime(2019, 11, 3))
datetime.datetime(2019, 11, 3, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
>>> tz_ny.localize(datetime(2019, 11, 4))
datetime.datetime(2019, 11, 4, 0, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
正如所见,DstTzInfo
与预期不同,因为纽约夏令时在 11 月 3 日结束。
共享代码示例在 localizing
11 月 3 日之前创建了 start
,它将 EDT
作为 tzinfo
分配给日期时间对象(使用夏令时)。要创建end
,1天的timedelta
被添加到start
,但是datetime
对象的tzinfo
是kept untouched:
>>> start = tz_ny.localize(datetime(2019, 11, 3))
>>> start.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>
>>> end = start + timedelta(days=1)
>>> end.tzinfo
<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>
因此 end
是 11 月 4 日的 datetime
,但 DstTzInfo
信息仍与 11 月 3 日相同。这不同于 localizing
11 月 4 日的天真 datetime
,它不使用夏令时。