Python 如何添加有关夏令时时区的每周时间增量

Python 如何添加有关夏令时时区的每周时间增量,python,datetime,timezone,dst,timedelta,Python,Datetime,Timezone,Dst,Timedelta,我想向本地化的datetime对象添加或减去周(或天、月或年)。问题是,由于夏令时时区的原因,这种幼稚的方法会导致1小时的轮班 2014-03-27 12:00就在冬季到夏季时间转换之前。如果我将一周的时间增量添加到此日期,例如,在欧洲/柏林时区本地化,结果将为2014-04-03 13:00。我想要同样的时间,2014-04-03 12:00。我找到了一个解决方案: from datetime import datetime, timedelta import pytz my_tz = pyt

我想向本地化的datetime对象添加或减去周(或天、月或年)。问题是,由于夏令时时区的原因,这种幼稚的方法会导致1小时的轮班

2014-03-27 12:00就在冬季到夏季时间转换之前。如果我将一周的时间增量添加到此日期,例如,在欧洲/柏林时区本地化,结果将为2014-04-03 13:00。我想要同样的时间,2014-04-03 12:00。我找到了一个解决方案:

from datetime import datetime, timedelta
import pytz
my_tz = pytz.timezone("Europe/Berlin")

def add_relativedelta(date, delta):
    """
    Adds the given timedelta to the given date. Shifts in timezone offsets
    will be removed.
    """
    tz = date.tzinfo
    result = tz.normalize(date + delta)
    if result.utcoffset() != date.utcoffset():
        result = tz.normalize(date.utcoffset() - result.utcoffset() + result)
    return result

date = my_tz.localize(datetime(year=2014, month=3, day=27, hour=12, minute=0))
print """{} Original localized date (winter time)
{} One week later (summer time)
{} Date one week later preserving hour of day (summer time)""".format(date,
                     my_tz.normalize(date + timedelta(days=7)),
                     add_relativedelta(date, timedelta(days=7)))


2014-03-27 12:00:00+01:00 Original localized date (winter time)
2014-04-03 13:00:00+02:00 One week later (summer time)
2014-04-03 12:00:00+02:00 Date one week later preserving hour of day (summer time)
我想知道是否有更通用/更好的解决方案。有没有图书馆可以解决这个问题?这似乎是一个非常常见的问题。

timedelta(days=7)
表示7天,如
7*24
小时,而不是“太阳日”。 如果向时区感知的datetime添加7天,则将获得7天之后的datetime,这与该datetime在时区中的表示方式无关

似乎您真正想要的是将增量应用于指定的时间,而忽略时区细节。请注意区别:

In [13]: print my_tz.normalize( my_tz.localize( dt ) + delta )
2014-04-03 13:00:00+02:00

In [14]: print my_tz.normalize( my_tz.localize( dt + delta ) )
2014-04-03 12:00:00+02:00

因此,如果可能的话,在对日期时间进行本地化之前将其应用于delta。

我试图从给定日期开始查找一周的开始和结束时间,但遇到了这个问题。我能够使用这个包实现一个支持DST的timedelta。我是这样做的:

from dataclasses import dataclass
from datetime import datetime

import arrow


@dataclass(frozen=True)
class Week:
    start: datetime
    end: datetime


def get_week_range(dt: datetime, tz: str) -> Week:
    """Returns Week instance with localized, time-aware start and end datetimes"""
    dt = arrow.get(dt, tz)
    start = dt.shift(days=-dt.weekday())
    end = start.shift(days=7).shift(seconds=-1)

    return Week(start=start, end=end)


>>> get_week_range(datetime(2020, 10, 27), "America/Chicago")
Week(start=<Arrow [2020-10-26T00:00:00-05:00]>, end=<Arrow [2020-11-01T23:59:59-06:00]>)
从数据类导入数据类
从日期时间导入日期时间
导入箭头
@数据类(冻结=真)
上课周:
开始:日期时间
完:日期时间
def get_week_范围(dt:datetime,tz:str)->周:
“”“返回具有本地化、时间感知的开始和结束日期时间的星期实例”“”
dt=箭头。get(dt,tz)
start=dt.shift(天数=-dt.weekday())
结束=开始。班次(天数=7)。班次(秒=-1)
返回周(开始=开始,结束=结束)
>>>获取周范围(日期时间(2020、10、27),“美国/芝加哥”)
周(开始=,结束=)
请注意,本例中返回的结束日期是如何正确调整为
-06:00
偏移量的,因为对于
美国/芝加哥
时区,夏令时在11月1日凌晨2点结束。

相关;如果必须包括DST变更: