Cron and time zones: CRON_TZ, TZ and daylight saving

Updated November 6, 2026

A crontab line has no time zone. 0 9 * * 1-5 means 9 AM in whatever time zone the cron daemon runs in, and that is often UTC on a cloud server, not the time zone of the people who care about the job. This guide shows how to find out which time zone cron uses, the ways to change it, and what happens around daylight saving time.

Which time zone does cron use?

Cron uses the system time zone it saw when the daemon started. Check it:

timedatectl | grep "Time zone"
date

If you change the system time zone with timedatectl set-timezone America/New_York, restart cron afterwards (systemctl restart cron, or crond on RHEL), or it may keep using the old one. In Docker containers there is often no time zone set at all, so cron runs in UTC unless you set TZ and install the tzdata package.

Option 1: keep the server in UTC and convert

Many teams keep every server in UTC and write schedules in UTC on purpose: logs from all machines line up, and nothing shifts twice a year. The cost is doing the arithmetic yourself. 9 AM in New York is 14:00 UTC in winter and 13:00 UTC in summer, so a fixed UTC line drifts by an hour against local time when the clocks change.

Option 2: CRON_TZ in the crontab

cronie, the cron on RHEL, Rocky, AlmaLinux, Fedora and Arch, supports a time zone for the schedule:

CRON_TZ=America/New_York
0 9 * * 1-5 /srv/report.sh

The lines after CRON_TZ are read in that time zone. The cron on Debian and Ubuntu doesn’t support it: the variable is passed to the job like any other, and the schedule stays in the system time zone. Check man 5 crontab on your server before you rely on it.

TZ=... in a crontab is a different thing. It sets the time zone the job sees, so date inside the script prints local time, but the schedule itself doesn’t move.

Option 3: a systemd timer with a time zone

systemd timers accept a time zone at the end of OnCalendar:

[Timer]
OnCalendar=Mon..Fri 09:00 America/New_York
Persistent=true

Check how systemd reads it with systemd-analyze calendar "Mon..Fri 09:00 America/New_York". The systemd timers guide shows the rest of the setup.

Kubernetes and other schedulers

Daylight saving time

Twice a year, local time either skips an hour or repeats one. In the United States and most of Europe, clocks move forward an hour in spring and back an hour in autumn, at night. A job scheduled inside that hour is the one that suffers:

Debian’s cron handles changes of less than three hours specially: jobs at fixed times that fall in the skipped period run right after the change, and jobs in the repeated hour run once. Other implementations differ. The safest choices are:

Monitor in the same time zone

A missed run is easiest to catch when the monitor knows the schedule exactly, in the same time zone as the job. In Heartcron each check has its own cron expression and time zone, and daylight saving is handled, so 0 9 * * 1-5 in America/New_York is expected at 9 AM New York time all year:

heartcron checks create weekday-report --cron "0 9 * * 1-5" --tz America/New_York --grace 15m

Then add the ping to the job. The cron expression explainer shows the next runs in any time zone, which is a quick way to check what an expression means before and after a time change.

More guides