我正在尝试获取适当的时间范围,以在用户本地时区的数据库(日期时间存储在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
[归一化通过将end
对象添加到timedelta
而构成的start
变量时,夏令时的更改会丢失。为什么会发生这种情况?
不确定日期时间计算的预期行为,但是我仅从共享代码示例中解释行为。
pytz.localize
创建一个时区感知日期时间实例。当将NY时区用于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日结束。
共享代码示例在11月3日start
之前创建localizing
,该操作将EDT
作为tzinfo
分配给日期时间对象(使用DST)。要创建end
,将1天的timedelta
添加到start
,但是tzinfo
对象的datetime
为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日相同。这与11月4日未使用DST的localizing
天真datetime
不同。