Time is cron's fuel — and a wrong timezone causes jobs to run at the wrong hour or twice. This episode covers CRON_TZ=Asia/Jakarta, the impact of Daylight Saving Time on daily jobs, and best practices: UTC for infrastructure and schedules at stable hours.

In episode 15 we moved cron into a Kubernetes cluster. Now we return to a base concept that's often overlooked: time. Cron matches time fields against the system clock — and if the system clock is in the wrong timezone, or that timezone has Daylight Saving Time (DST) rules, even "correct" schedules can run at the wrong hour.
Indonesia doesn't observe DST, but a lot of the infrastructure you manage can be connected to regions that do (e.g. Europe or North America). This episode covers how cron handles timezone and DST, plus a policy that avoids these problems for good.
Cron reads the host's local time by default — from the system localtime. This is why a server in Jakarta and one in New York both execute 0 2 * * * in their respective local times.
Check the host timezone:
timedatectl
dateCronie provides CRON_TZ to set a timezone for a crontab — without changing the host's zone:
CRON_TZ=Asia/Jakarta
30 2 * * * /usr/local/bin/backup.shWith CRON_TZ=Asia/Jakarta, the schedule is evaluated in Jakarta time, regardless of the host zone. This matters for jobs that must align with local business hours — e.g. a report that must be ready before the office opens at 07.00 WIB.
CRON_TZ=Asia/Jakarta
SHELL=/bin/bash
30 6 * * 1-5 /usr/local/bin/morning-report.shNote
CRON_TZ uses the tzdata (IANA) database — zone names like Asia/Jakarta, Asia/Makassar, or Etc/UTC. The name must be valid; check with timedatectl list-timezones | grep Asia. Zone names are more reliable than offsets like +7 because they follow DST rules automatically.
In timezones with DST, the clock jumps forward one hour in spring ("spring forward") and back in autumn ("fall back"). Its impact on cron:
30 2 * * * job doesn't run that day.Both are potentially damaging: jobs that are skipped, and jobs that double up.
Even servers in Indonesia can feel this if:
CRON_TZ points to a DST-observing zone, orThe policy most widely used in the industry: the entire infrastructure runs on UTC, and conversion to local zones happens in the presentation layer (applications), not in scheduling.
sudo timedatectl set-timezone UTC
timedatectlThe benefits:
For jobs that must run at a specific local hour while the host runs UTC, express them in UTC:
30 19 * * * /usr/local/bin/backup.shOr combine with CRON_TZ when it's clearer from a business perspective:
CRON_TZ=Asia/Jakarta
30 2 * * * /usr/local/bin/backup.shTip
Pick one pattern and stay consistent. Mixing UTC and CRON_TZ without documentation is the biggest source of confusion. Recommendation: hosts and logs in UTC, CRON_TZ only for jobs that genuinely follow local business time, and always write a comment in the crontab explaining the zone in use.
| Situation | Practice |
|---|---|
| General infrastructure | Host UTC, logs UTC |
| Jobs following local business time | CRON_TZ=Asia/Jakarta |
| DST-observing regions | Avoid the jumping hours; use UTC |
| Sensitive daily jobs | Schedule at stable hours, avoid 02.00 in DST zones |
| Team coordination | One language: UTC |
Key takeaways:
CRON_TZ sets a per-crontab zone.CRON_TZ only for jobs that follow local business time.In episode 17 we'll cover Cronie 1.7.x and its latest features — the MAILFROM fix, the -n option to wait for jobs to finish, integrated anacron, and a full comparison of cronie vs vixie-cron vs systemd timers vs at!