← Back to Blog
Guide schedule cron timezone dst

Cron Jobs, Time Zones, and Daylight Saving

Twice a year, scheduled jobs run twice or not at all. The fix for most of it is moving one job off 2am — here's the rest.

JW

Jason Warner

July 31, 2026

Cron Jobs, Time Zones, and Daylight Saving

Every March and November, a small number of scheduled jobs quietly do the wrong thing. A nightly report goes out twice. A billing run doesn't happen. An export starts landing an hour late and stays that way for six months before anyone connects it to the clocks changing.

It's one of the most predictable bugs in scheduled work, and it comes down to a decision most people make without realising they're making it: what clock the cron expression is read against.

Clocks Don't Move Smoothly

Daylight saving doesn't shift time — it deletes an hour in spring and repeats one in autumn.

Going forward, 2:00am becomes 3:00am and the hour between never exists. A job set for 30 2 * * * has no valid moment to run that night. Depending on the scheduler it fires at 3:00, or at 1:30, or it doesn't fire at all — and skipping is a completely defensible implementation choice, which is why you can't assume.

Going back, 2:00am returns to 1:00am and the 1am hour happens twice. A job set for 30 1 * * * now has two valid moments. Some schedulers fire once, some fire twice. If that job charges cards or sends email, twice is a bad night.

Which gives you the rule that prevents most of these incidents outright:

Don't schedule anything between 1am and 3am local time.

Every DST edge case lives in that window. Move the job to 4am and the entire problem evaporates for free. I'd take that trade over understanding the edge cases any day.

UTC Is Predictable, and Sometimes Wrong

Running everything in UTC is the standard advice and it's correct about the important thing: UTC has no daylight saving, so every schedule fires exactly once at a predictable instant. Nothing duplicates, nothing vanishes.

What it costs you is alignment with humans. 0 13 * * * in UTC is 9am in New York during EDT and 8am during EST. If the job produces a report someone reads with their morning coffee, it now shows up an hour early for half the year. Nothing is broken exactly — but the requirement was "9am," and for six months a year you're not meeting it.

So: UTC for machine-facing work. Syncs, cleanups, cache warming, anything with no person on the other end.

Local Time Needs a Real Zone

When the job exists to line up with human activity — a morning digest, an end-of-day report, a reminder before a shift starts — you want it tracking local time through the transitions. That means an IANA zone like America/New_York, not a fixed offset like UTC-5.

The distinction looks pedantic and isn't. A fixed offset cannot follow daylight saving; it's a constant, that's what it means. America/New_York is a rule set that knows about EST and EDT and when each applies, so 9am stays 9am all year.

In Bluejay Schedule a job carries an IANA timezone and the expression is evaluated in it, so 0 9 * * 1-5 in America/New_York is 9am on weekdays through both transitions. Leave it unset and you get UTC, which is the right default.

Choosing the Zone

Ask what the schedule is anchored to.

Anchored to Use
A person's working day Their IANA zone
A business's opening hours The business's zone
A billing or calendar period The zone the period is defined in
Another system's daily cutoff That system's zone
Nothing human UTC

The mistake worth naming: using the timezone of whoever set the job up. Someone in Frankfurt configuring a morning report for a team in Chicago should be picking America/Chicago. Otherwise the report shifts by an hour twice a year, for reasons entirely invisible to the people it shifts for.

It's Not Just Europe and North America

DST isn't universal and isn't synchronised. Australia and New Zealand transition in October and April, opposite to the northern hemisphere. Much of Asia and Africa doesn't observe it at all. Some countries change the rules with a few months' notice, and a few have abolished it recently enough that stale software still gets it wrong.

This is exactly why IANA identifiers exist. Australia/Sydney carries the rules and their history. "UTC+10" carries an assumption that's wrong for part of the year, every year.

The Two-Minute Version

Avoid 1am–3am local for anything daily. Use UTC when no human is involved and an IANA zone when one is. Never use a fixed offset for a schedule meant to track local time. Make the job idempotent so a duplicate run during a fall-back is a non-event.

Then check your run history the morning after each transition. One execution on the Sunday means everything worked; two or none means you found out on your own terms rather than from a customer on Monday. Twice a year, sixty seconds. Cheapest insurance available.


Schedule jobs in real time zones, not fixed offsets. Try Bluejay Schedule free.

#schedule #cron #timezone #dst

Schedule your first HTTP job with confidence

Set up in minutes. Free to start.

Start scheduling free