从 America/New_York 时间到 UTC 再转换回 America/New_York 的日期时间转换不正确

for*_*Dev 2 python datetime pytz

我正在尝试将美国/纽约的时间转换为 UTC 时间,然后将其转换回纽约时间。但我在使用 时得到了不同的结果pytz

我正在这样做:

new_date = parser.parse("May 4, 2021")
new_date = new_date.replace(tzinfo=pytz.timezone("America/New_York"))
date = new_date.astimezone(pytz.timezone("UTC"))     
Run Code Online (Sandbox Code Playgroud)

输出:

datetime.datetime(2021, 5, 4, 4, 56, tzinfo=<UTC>)
Run Code Online (Sandbox Code Playgroud)

当我尝试将其重新转换回纽约时间时,我得到以下信息:

date.astimezone(pytz.timezone("America/New_York"))
Run Code Online (Sandbox Code Playgroud)

我得到:

datetime.datetime(2021, 5, 4, 0, 56, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么会有 56 分钟的差异,可以采取什么措施来防止这种情况发生?

MrF*_*pes 5

56 分钟的差异源于以下事实:访问的数据库中的第一个条目pytz指的是 LMT(当地时间):

import pytz
t = pytz.timezone("America/New_York")
print(repr(t))
# <DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
Run Code Online (Sandbox Code Playgroud)

您可以在 P. Ganssle 的Fastest Footgun博客文章或SO 上的pytz 的奇怪时区问题中阅读更多内容。

tl;dr - 切勿replace使用带有时区对象的 tzinfo pytz使用localize(或astimezone) 来代替,将时区调整为日期时间对象的年份。

...但是:既然你dateutil已经使用了,为什么不在这里也使用它:

import dateutil

new_date = dateutil.parser.parse("May 4, 2021")
# you can safely replace with dateutil's tz objects:
new_date = new_date.replace(tzinfo=dateutil.tz.gettz("America/New_York"))
date = new_date.astimezone(dateutil.tz.UTC)   

# date
# datetime.datetime(2021, 5, 4, 4, 0, tzinfo=tzutc())

date = date.astimezone(dateutil.tz.gettz("America/New_York"))
# date
# datetime.datetime(2021, 5, 4, 0, 0, tzinfo=tzfile('US/Eastern'))
print(date)
# 2021-05-04 00:00:00-04:00
Run Code Online (Sandbox Code Playgroud)