April 8, 2026 · 7 min read
How cron handles timezones and daylight saving time
A cron expression has no timezone in it. The daemon interprets 0 2 * * * against whatever the machine's clock says local time is. Twice a year, on the days the clocks change, that job's timing moves.
Cron uses the system timezone
Classic Unix cron reads the system timezone (/etc/localtime, or the TZ environment variable) and evaluates every schedule against it. There is historically no per-job timezone. If the box is set to America/New_York, 0 2 * * * runs at 2 a.m. Eastern; if it's set to UTC, it runs at 2 a.m. UTC.
This is fine until the schedule interacts with a daylight-saving transition, because on those two days “2 a.m. local” is either a time that doesn't exist or a time that happens twice.
Spring forward: the skipped hour
When the clocks jump from 02:00 straight to 03:00, any job scheduled for a specific time inside that missing hour has no matching minute to run at. Vixie cron and cronie handle this deliberately: a fixed-time job in the skipped interval is run once, shortly after the jump.
30 2 * * *on spring-forward day: 02:30 never occurs, so cron runs the job when the clock reaches 03:00.*/10 * * * *: wildcard schedules just resume on the new time. The 02:1x, 02:2x, ... slots are skipped and the job picks up at 03:00, 03:10, and so on.
Fall back: the repeated hour
When the clocks go from 02:00 back to 01:00, the hour from 01:00 to 02:00 happens twice. Here the rule flips: a fixed-time job in the repeated interval runs once, not twice.
30 1 * * *on fall-back day: 01:30 occurs twice; cron runs the job on the first pass only.*/10 * * * *: wildcard schedules do run again through the repeated hour. They match every tenth minute regardless of what hour it is.
The documented summary, from the Debian cron manual: if the clock moved forward, jobs that would have run in the skipped interval run soon after the change; if it moved back by less than three hours, jobs in the repeated interval are not re-run. Only fixed-time jobs are affected. Wildcard jobs run on the new time immediately.
Setting a timezone per crontab: CRON_TZ
Vixie cron and cronie support a CRON_TZ variable that sets the timezone for the entries after it, without changing the whole machine's clock.
CRON_TZ=UTC
0 6 * * * /usr/local/bin/nightly-export # 06:00 UTC, no DST
CRON_TZ=America/Chicago
0 8 * * 1-5 /usr/local/bin/send-daily-digest # 08:00 Central, shifts with DSTCRON_TZ is not universal. Some cron implementations ignore it, so confirm your daemon supports it before relying on it.
Other schedulers
- systemd timers evaluate
OnCalendar=in the configured timezone and handle DST transitions;Persistent=truealso catches up missed runs. Generally the more predictable option on modern Linux. - Kubernetes CronJob has a
spec.timeZonefield (GA in 1.27). Without it, schedules use the kube-controller-manager's zone. - AWS EventBridge Scheduler and Google Cloud Scheduler both take an explicit timezone argument and apply DST rules for it.
Practical advice
- Run cron in UTC if you can. No DST, no ambiguous or missing hours, and logs line up across regions. Convert to local time for display, not for scheduling.
- If you need local time, use
CRON_TZor a scheduler with an explicit timezone and documented DST behaviour. - Avoid scheduling anything between roughly 00:00 and 03:00 local in a DST-observing zone. That window is where the skipped and repeated hours land, and it is where surprises happen.
The transition rules come from the IANA time zone database, which every serious scheduler consults rather than guessing. Falsehoods programmers believe about time covers the rest of the ways time breaks software.
Cron itself usually does something reasonable on the transition. The false alarm comes from a naive monitor that expects a ping “every 24 hours” and trips when the interval runs 23 or 25 hours across the changeover.
That is the case illari is built for: give it the cron expression and an IANA timezone, and it computes each expected run in that zone with the transitions handled, so a 0 2 * * * job doesn't page you on the changeover weekend. The cron expression tester shows the same computation, and flags any daylight-saving change in the upcoming runs.
Monitor a scheduled job with illari
Your job pings a URL when it runs. Miss the window and you get an alert. 25 monitors free, no credit card.