I'm doing some datetime math in python with the pytz library (although I'm open to using other libraries if necessary). I have an iterator that needs to increase by one day for each iteration of the loop. The problem comes when transitioning from November 3rd to November 4th in the Eastern timezone, which crosses the daylight saving boundary (there are 25 hours between the start of November 3rd and the start of November 5th, instead of the usual 24). Whenever I add a "day" that crosses the boundary, I get a time that is 24 hours in the future, instead of the expected 25.
This is what I've tried:
import datetime
import pytz
ET = pytz.timezone("US/Eastern")
first_day = ET.localize(datetime.datetime(2024, 11, 3))
next_day = first_day + datetime.timedelta(days=1)
first_day.isoformat() # '2024-11-03T00:00:00-04:00'
next_day.isoformat() # '2024-11-04T00:00:00-04:00'
assert next_day == ET.localize(datetime.datetime(2024, 11, 4)) # This fails!!
# I want next_day to be '2024-11-04T00:00:00-05:00' or '2024-11-04T01:00:00-04:00'
I also tried throwing a normalize()
in there, but that didn't produce the right result either:
ET.normalize(next_day).isoformat() # '2024-11-03T23:00:00-05:00'
(That's one hour earlier than my desired output)
I suppose I could make a copy of my start_day that increments the day
field, but then I'd have to be aware of month and year boundaries, which doesn't seem ideal to me.
It looks like you want "wall time", which is the same "wall clock" time the next day, regardless of daylight savings time transitions. I would use the built-in zoneinfo
module. You may need to install the "1st party" tzdata
module if using Windows to have up-to-date time zone information (pip install tzdata
):
import datetime as dt
import zoneinfo as zi
ET = zi.ZoneInfo('US/Eastern')
first_day = dt.datetime(2024, 11, 3, tzinfo=ET) # time zone aware
next_day = first_day + dt.timedelta(days=1) # "wall clock" math in time zone
print(first_day)
print(next_day)
assert next_day == dt.datetime(2024, 11, 4, tzinfo=ET)
Output:
2024-11-03 00:00:00-04:00
2024-11-04 00:00:00-05:00
Note that if instead you want exactly 24 hours later regardless of DST transitions, do the time delta math in UTC:
import datetime as dt
import zoneinfo as zi
ET = zi.ZoneInfo("US/Eastern")
first_day = dt.datetime(2024, 11, 3, tzinfo=ET) # time zone aware
# Convert to UTC, do math, convert back to desired time zone
next_day = (first_day.astimezone(dt.UTC) + dt.timedelta(days=1)).astimezone(ET)
print(first_day)
print(next_day)
Output:
2024-11-03 00:00:00-04:00
2024-11-03 23:00:00-05:00