Cron time zones and daylight saving: why your job runs at the wrong hour
Cron has no idea where you are. It follows the server's clock, and twice a year that clock does something strange. Here is how to control both.
A job scheduled for 9:00 that fires at 4:00, or one that ran twice on a Sunday in November, has the same root cause. Cron works in local time, and “local” means the machine’s idea of it, not yours.
Which time zone does cron use?
Traditional cron reads the system time zone when it starts and applies it to every crontab on the machine. Check what that is:
timedatectl # Time zone: Etc/UTC (UTC, +0000)
date
Cloud servers, containers and CI runners are nearly always on UTC. That is a sensible default for servers, but it means a crontab written with your office hours in mind is off by several hours, and by a different amount in summer and winter if your own time zone uses daylight saving.
The cron expression generator shows the next run times in your own time and in UTC side by side, which is the quickest way to see the gap.
Three ways to run a job at the right local time
Convert the time to UTC yourself. If the server stays on UTC, write the schedule in
UTC. 0 14 * * 1-5 runs at 14:00 UTC, which is 9:00 in New York in winter and 10:00 in
summer. That drift is the catch: a fixed UTC time moves by an hour against your local
clock when daylight saving changes. For many jobs it does not matter. For a report
someone expects at 9:00 sharp, it does.
Give the crontab its own time zone. Cronie, the cron used by Red Hat, Fedora, CentOS
and Rocky Linux, reads a CRON_TZ variable at the top of a crontab and schedules every
line below it in that zone:
CRON_TZ=America/New_York
0 9 * * 1-5 /srv/reports/daily.sh
Debian and Ubuntu ship a different cron that does not support CRON_TZ. Setting TZ in
the crontab there only changes the environment your command sees, not when it runs, which
catches a lot of people out.
Change the machine’s time zone. sudo timedatectl set-timezone Europe/London makes
cron follow that local time, daylight saving included. Restart cron afterwards so it
picks up the change. This suits a machine with one job to do, but it affects everything
else on it too, log timestamps included.
Scheduling platforms have added their own options. Kubernetes CronJobs accept a
timeZone field such as America/New_York from version 1.27, and GitHub Actions has let
you add a timezone next to a scheduled workflow’s cron line since March 2026. Both
follow daylight saving for you, so the UTC arithmetic is no longer needed there.
What happens when the clocks change
Daylight saving creates one hour that never happens in spring and one hour that happens twice in autumn. In time zones that change at 2:00, anything scheduled between 2:00 and 3:00 is in the danger zone.
The cron on most Linux servers, both cronie and the version on Debian and Ubuntu, has a special rule for jobs that run at a fixed time:
- When the clocks go forward, a job set for 2:30 does not simply vanish. Cron notices it was skipped and runs it straight away, at 3:00.
- When the clocks go back and 1:00 to 2:00 happens twice, a job set for 1:30 runs once, not in both copies of the hour.
Jobs that run more than once an hour, such as every 15 minutes, just follow the clock and are not adjusted. A job every 15 minutes runs four extra times in the repeated hour in autumn and four fewer times in spring. Many other schedulers, including plenty of language libraries and some managed services, have no special handling at all.
The simple rule
Keep important daily jobs out of the hours between 1:00 and 3:00 local time, or run them on a machine set to UTC, which has no daylight saving. Either way the question never comes up.
A checklist for time zone bugs
- Run
dateon the server and compare it with your own clock. - Decide whether the job should follow UTC or a local time, and note it next to the job.
- On cronie, use
CRON_TZ. On Debian or Ubuntu, convert to UTC or change the system time zone. - Check the next run times in both zones in the cron generator.
- Move anything scheduled between 1:00 and 3:00 to a safer hour.
If the job still does not run at all, the time zone is not the problem. The guide to cron jobs that do not run covers the other causes.