为什么对于萨摩亚的pytz和dateutil我得到不同的结果?

时间:2018-09-02 12:23:34

标签: python datetime pytz python-dateutil

我期望以下两个结果相同,但事实并非如此。为什么会这样呢?

版本:

pytz==2018.5
python-dateutil==2.7.3

示例1:pytz

import datetime
import pytz

tz = pytz.timezone('Pacific/Apia')
today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                              tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz)
print(today_tz.isoformat())

打印2011-12-29T23:59:00-10:00(正确)

示例2:dateutil

import datetime
import dateutil.tz

tz = dateutil.tz.gettz('Pacific/Apia')
today_utc = datetime.datetime(2011, 12, 30, 9, 59,
                              tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz)
print(today_tz.isoformat())

打印2011-12-29T23:59:00+14:00(这是错误的)

1 个答案:

答案 0 :(得分:2)

您发现了一个bug in dateutil,我现在已经将其报告为fixed

该错误是由于在dateutil中如何计算转换的“墙时”而引起的,该问题做出了一些假设,而这些假设在DST < / em>。扩展您的示例:

from datetime import datetime, timedelta
from dateutil import tz
import pytz

APIA = tz.gettz('Pacific/Apia')
APIA_p = pytz.timezone('Pacific/Apia')
dt0 = datetime.fromisoformat('2011-12-29T20:00-10:00')

for i in range(5):
    dt = (dt0 + timedelta(hours=i))
    dt_d = dt.astimezone(APIA)
    dt_p = dt.astimezone(APIA_p)
    print(f'{dt_d.isoformat()}, {dt_p.isoformat()}')

## Result:
# 2011-12-29T20:00:00-10:00, 2011-12-29T20:00:00-10:00
# 2011-12-29T21:00:00-10:00, 2011-12-29T21:00:00-10:00
# 2011-12-29T22:00:00-10:00, 2011-12-29T22:00:00-10:00
# 2011-12-29T23:00:00+14:00, 2011-12-29T23:00:00-10:00
# 2011-12-31T00:00:00+14:00, 2011-12-31T00:00:00+14:00

您可以看到dateutil总是可以正确计算日期和时间,但是当isoformat调用utcoffset时,偏移量更改会提前1小时发生。这是因为astimezone会在后台调用tzinfo.fromutc,而isoformat会调用utcoffsetdateutil将转换时间存储在UTC和本地时间中,UTC时间用在fromutc中,本地时间用在utcoffsetdst和{{1}中}。该错误涉及在DST-> DST过渡期间计算过渡的“时间”(这非常少见)时过度补偿了DST,这就是为什么它不影响tzname的原因。

底线-您同时正确使用astimezonepytz,此错误将在下一版本中得到解决。

注意:在我找到了引起该错误的原因并修复该错误之后,对该答案进行了编辑。