为什么我对萨摩亚的 pytz 和 dateutil 得到不同的结果?
Why do I get different results for pytz and dateutil for Samoa?
我原以为下面两个会给出相同的结果,但他们没有。为什么会这样?
版本:
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
(这是错误的)
您发现了 bug in dateutil
, which I have now reported and fixed。
该错误是由于 "wall time" 中的转换在 dateutil
中的计算方式问题引起的,当时时区的基准偏移量发生变化 [=40] 时做出了一些不成立的假设=]夏令时期间。稍微扩展一下您的示例:
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
under the hood, while isoformat
calls utcoffset
。 dateutil
以 UTC 和本地时间存储转换时间,UTC 时间用于 fromutc
,本地时间用于 utcoffset
、dst
和 tzname
.此错误涉及在 DST->DST 转换期间计算转换的 "wall time" 时对 DST 的过度补偿(这种情况极为罕见),这就是它不影响 astimezone
.[=30= 的原因]
底线 - 您正确使用了 pytz
和 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
(这是错误的)
您发现了 bug in dateutil
, which I have now reported and fixed。
该错误是由于 "wall time" 中的转换在 dateutil
中的计算方式问题引起的,当时时区的基准偏移量发生变化 [=40] 时做出了一些不成立的假设=]夏令时期间。稍微扩展一下您的示例:
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
under the hood, while isoformat
calls utcoffset
。 dateutil
以 UTC 和本地时间存储转换时间,UTC 时间用于 fromutc
,本地时间用于 utcoffset
、dst
和 tzname
.此错误涉及在 DST->DST 转换期间计算转换的 "wall time" 时对 DST 的过度补偿(这种情况极为罕见),这就是它不影响 astimezone
.[=30= 的原因]
底线 - 您正确使用了 pytz
和 dateutil
,此错误将在下一个版本中修复。
注意:这个答案是在我找到错误的原因并修复后编辑的。