The default timezone
By default, cron uses the system's local timezone — the same one shown by date or timedatectl.
On cloud servers, this is almost always UTC. On developer laptops or on-prem servers, it's whatever was set at install time. To check:
date # Shows current local time + timezone timedatectl # systemd; also shows the TZ name (e.g. "America/New_York") cat /etc/timezone # The configured timezone name on Debian/Ubuntu readlink /etc/localtime # Symlink target on most modern Linuxes
Setting CRON_TZ in your crontab
Vixie cron 4.0 and newer (the default on most Linux distributions) supports a CRON_TZ variable at the top of the crontab. It changes the timezone for all jobs in that crontab:
CRON_TZ=America/New_York # Now this means 9 AM Eastern, not 9 AM UTC: 0 9 * * 1-5 /path/to/script.sh
The value must be a tz database name (IANA timezone name). America/New_York works; EST usually does not. UTC works everywhere as an explicit timezone.
CRON_TZ only affects when jobs fire. It does NOT set TZ inside the running job — your script still sees the system timezone unless you set TZ separately.Per-job timezone with the TZ env var
You can set TZ on a single job by prefixing it:
0 9 * * 1-5 TZ='America/Los_Angeles' /path/to/script.sh
This affects what your script sees inside (e.g., date commands in the script), but it does NOT affect when cron fires the job. To control both the firing time AND the script's view, use both:
CRON_TZ=America/Los_Angeles 0 9 * * 1-5 TZ='America/Los_Angeles' /path/to/script.sh
Changing the system timezone
If you control the server and want everything in a specific timezone, change the system TZ instead of fighting per-job overrides:
sudo timedatectl set-timezone America/New_York sudo systemctl restart cron # Reload cron with the new TZ
This affects all users, all jobs, the system clock display, log timestamps — everything. Use with care on shared servers.
Platform-by-platform behavior
Linux/macOS crontab
System timezone unless overridden by CRON_TZ. Vixie cron + cronie on RHEL, ISC cron on Debian/Ubuntu, all support the same basic mechanism.
systemd timers
System timezone by default. Per-timer override with OnCalendar=Mon..Fri 09:00 America/New_York syntax. Recommended over crontab for modern systems because the syntax is explicit.
Kubernetes CronJob
UTC always — until Kubernetes 1.27. From 1.27+, set spec.timeZone: "America/New_York":
apiVersion: batch/v1 kind: CronJob metadata: name: nightly-backup spec: schedule: "0 2 * * *" timeZone: "America/New_York" jobTemplate: ...
Older clusters: run in UTC and convert mentally, or set TZ in the container spec.
AWS EventBridge
UTC always for classic EventBridge cron expressions. No per-rule timezone setting. AWS introduced "EventBridge Scheduler" (a separate service) in late 2022 that supports timezones via the ScheduleExpressionTimezone field.
GitHub Actions
UTC always. No override. Period. If you need 9 AM Pacific, schedule for 17:00 (or 16:00 during DST) UTC and accept the half-year drift, or use an external scheduler to trigger via workflow_dispatch.
GCP Cloud Scheduler
Per-job time_zone setting. Default UTC, but specifying America/New_York works. This is one of the cleaner timezone implementations.
Quartz
Per-trigger. Use CronScheduleBuilder.cronSchedule("0 0 9 ? * MON-FRI").inTimeZone(TimeZone.getTimeZone("America/New_York")). Defaults to the JVM's timezone (which inherits from the OS).
Spring @Scheduled
The zone attribute:
@Scheduled(cron = "0 0 9 * * MON-FRI", zone = "America/New_York")
public void run() { ... }
Default is the JVM's timezone.
Best practices
- For server-side batch jobs, use UTC. Eliminates DST and ambiguity entirely. Convert your "I want it at 9 AM Eastern" requirement to the equivalent UTC hour and document the choice.
- For user-facing scheduled tasks (notifications, reports for end users), use a real scheduler with timezone support. Cloud Scheduler, EventBridge Scheduler, or Quartz. Don't try to make UTC-only services do something they can't.
- Document the timezone in every cron file with a comment at the top:
# All times in UTC unless prefixed with TZ 0 9 * * 1-5 ...
- Verify the timezone explicitly in your application's logs. If "9:00:00" appears in logs, it should be obvious whether that's UTC or local.
- Don't trust the abbreviations. "EST" might mean Eastern Standard Time on one system and Egypt Standard Time on another. Always use full IANA names like
America/New_York.