I want to add or subtract weeks (or days or month or years) to localized datetime objects. The problem is, that the naive approach will result in 1 hour shifts due to daylight s
I was trying to find the start and end of a week from a given date and I ran into this issue. I was able to achieve a DST-aware timedelta using the arrow package. Here's how I did it:
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]>)
Notice how the returned end date in this example is correctly adjusted to -06:00
offset since daylight savings ends on 11/1 at 2am for America/Chicago
time zone.
timedelta(days=7)
means 7 days, as in 7*24
hours - not "solar days".
If you add 7 days to a timezone-aware datetime, you'll obtain a datetime that is 7 days later - independently of how that datetime is represented in the timezone.
It seems what you really want is to apply the delta to the time you specified, ignoring timezone details. Notice the difference:
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
So, if possible, apply the deltas to the datetimes before they are localized.