在 DST 添加时间增量后时区转换错误
Wrong timezone shift after adding a time delta over DST
我正在尝试将一个 tz 感知时间戳移动一个月。由于 datetime.timedelta
没有月份选项,因此应使用包 relativedelta
。
问题出现在时间点在夏令时之后,移位后的结果会在夏令时之前。
例如将 2022-04-26 07:00:00+02:00
移回一个月。预期是 2022-03-26 07:00:00+01:00
然而,结果将是 2022-03-26 07:00:00+02:00
(+02:00 而不是 +01:00)
这是一个代码示例:
import pytz
import datetime
from dateutil.relativedelta import relativedelta
berlin = pytz.timezone("Europe/Berlin")
base_date = berlin.localize(datetime.datetime(2022, 4, 26, 7, 0))
offset = relativedelta(months=1, day=0,
hour=base_date.hour, minute=base_date.minute,
second=base_date.second, microsecond=0)
shifted = base_date - offset
expected = berlin.localize(datetime.datetime(2022, 3, 26, 7, 0))
print("shifted: ", shifted)
print("expected: ", expected)
这将打印:
shifted: 2022-03-26 07:00:00+02:00
expected: 2022-03-26 07:00:00+01:00
结果是错误的,因为那一天 2022-03-26 CET
必须总是有 +1 小时的班次。
看来您需要使用 .astimezone
才能获得所需的结果。如下所示。
import pytz
import datetime
from dateutil.relativedelta import relativedelta
berlin = pytz.timezone("Europe/Berlin")
base_date = berlin.localize(datetime.datetime(2022, 4, 26, 7, 0))
offset = relativedelta(months=1)
shifted = (base_date - offset).astimezone(berlin)
# shifted = shifted.astimezone(berlin)
expected = berlin.localize(datetime.datetime(2022, 3, 26, 7, 0))
print("base:", base_date)
print("shifted: ", shifted)
print("expected: ", expected)
我在 PyTz
的示例和用法下找到了这个
既然你用了dateutil
,为什么不用它来处理tz呢?
from datetime import datetime
import dateutil
offset = dateutil.relativedelta.relativedelta(months=1)
dt = datetime(2022,4,26,7,tzinfo=dateutil.tz.gettz("Europe/Berlin"))
print(dt, dt-offset)
# 2022-04-26 07:00:00+02:00 2022-03-26 07:00:00+01:00
旁注,dateutil 语义也与 Python 3.9 way to handle time zone 一致。
我正在尝试将一个 tz 感知时间戳移动一个月。由于 datetime.timedelta
没有月份选项,因此应使用包 relativedelta
。
问题出现在时间点在夏令时之后,移位后的结果会在夏令时之前。
例如将 2022-04-26 07:00:00+02:00
移回一个月。预期是 2022-03-26 07:00:00+01:00
然而,结果将是 2022-03-26 07:00:00+02:00
(+02:00 而不是 +01:00)
这是一个代码示例:
import pytz
import datetime
from dateutil.relativedelta import relativedelta
berlin = pytz.timezone("Europe/Berlin")
base_date = berlin.localize(datetime.datetime(2022, 4, 26, 7, 0))
offset = relativedelta(months=1, day=0,
hour=base_date.hour, minute=base_date.minute,
second=base_date.second, microsecond=0)
shifted = base_date - offset
expected = berlin.localize(datetime.datetime(2022, 3, 26, 7, 0))
print("shifted: ", shifted)
print("expected: ", expected)
这将打印:
shifted: 2022-03-26 07:00:00+02:00
expected: 2022-03-26 07:00:00+01:00
结果是错误的,因为那一天 2022-03-26 CET
必须总是有 +1 小时的班次。
看来您需要使用 .astimezone
才能获得所需的结果。如下所示。
import pytz
import datetime
from dateutil.relativedelta import relativedelta
berlin = pytz.timezone("Europe/Berlin")
base_date = berlin.localize(datetime.datetime(2022, 4, 26, 7, 0))
offset = relativedelta(months=1)
shifted = (base_date - offset).astimezone(berlin)
# shifted = shifted.astimezone(berlin)
expected = berlin.localize(datetime.datetime(2022, 3, 26, 7, 0))
print("base:", base_date)
print("shifted: ", shifted)
print("expected: ", expected)
我在 PyTz
的示例和用法下找到了这个既然你用了dateutil
,为什么不用它来处理tz呢?
from datetime import datetime
import dateutil
offset = dateutil.relativedelta.relativedelta(months=1)
dt = datetime(2022,4,26,7,tzinfo=dateutil.tz.gettz("Europe/Berlin"))
print(dt, dt-offset)
# 2022-04-26 07:00:00+02:00 2022-03-26 07:00:00+01:00
旁注,dateutil 语义也与 Python 3.9 way to handle time zone 一致。