Bug Description
When Daylight Saving Time ends and clocks fall back by one hour, jobs scheduled with timezone-aware .at() times can stop running entirely. The _schedule_next_run method calculates the next run time incorrectly during the DST transition, causing next_run to be set to a time that never arrives or gets stuck in a loop.
Steps to Reproduce
import schedule
# Schedule a job at a specific time in a DST-observing timezone
schedule.every().day.at("02:30", "Europe/Berlin").do(my_job)
# When clocks fall back from 3:00 to 2:00 on the last Sunday of October,
# the scheduler either:
# 1. Stops scheduling the job entirely
# 2. Schedules it at the wrong time
# 3. Runs it twice (once for each occurrence of 2:30)
Root Cause
The _correct_utc_offset method in Job doesn't properly handle the ambiguous time period during DST fall-back transitions. When a local time occurs twice (e.g., 2:30 AM occurs once in CEST and once in CET), the method may pick the wrong occurrence or fail to advance past the transition.
Fix
The fix should handle the fold attribute on datetime objects to disambiguate times during DST transitions. When computing the next run after a DST fall-back:
- Use
datetime.fold = 1 to select the second (post-transition) occurrence
- Ensure
_correct_utc_offset properly advances past the transition
References
Bug Description
When Daylight Saving Time ends and clocks fall back by one hour, jobs scheduled with timezone-aware
.at()times can stop running entirely. The_schedule_next_runmethod calculates the next run time incorrectly during the DST transition, causingnext_runto be set to a time that never arrives or gets stuck in a loop.Steps to Reproduce
Root Cause
The
_correct_utc_offsetmethod inJobdoesn't properly handle the ambiguous time period during DST fall-back transitions. When a local time occurs twice (e.g., 2:30 AM occurs once in CEST and once in CET), the method may pick the wrong occurrence or fail to advance past the transition.Fix
The fix should handle the
foldattribute on datetime objects to disambiguate times during DST transitions. When computing the next run after a DST fall-back:datetime.fold = 1to select the second (post-transition) occurrence_correct_utc_offsetproperly advances past the transitionReferences