DEV Community

Cover image for Handling Timezone Issues in Cron Jobs (2025 Guide)
Łukasz Maśląg for CronMonitor

Posted on • Originally published at cronmonitor.app

Handling Timezone Issues in Cron Jobs (2025 Guide)

Troubleshooting Time Zone Issues in Cron Jobs
How to deal with different time zones when configuring crontab jobs.

Adding a job to a crontab seems simple at first glance, but problems can arise when the job is scheduled to run at the same time but in different time zones.

Jobs suddenly start an hour early, reports are generated overnight, or backups overlap after daylight saving time or winter time.

If you've ever asked yourself:

  • "Why does the job run twice?"
  • "Why doesn't the job run at all?"
  • "Why does the production environment behave differently than the test environment?"

—this article is for you.

1. The Main Problem: Cron Runs in Server Time, Not Real Time

By default, cron uses the server's time zone.

$ date
Thursday, January 2, 2026, 7:00 PM CET
Enter fullscreen mode Exit fullscreen mode

If your server is in the UTC, CET, PST time zone... but the application's business logic assumes a completely different time zone.

2. The Silent Killer: Daylight Saving Time (DST)

DST causes two critical problems:

❌ The job runs twice

When we turn back the clocks:

02:00 → 01:00
Enter fullscreen mode Exit fullscreen mode

A cron job scheduled for 01:30 may run twice.

❌ The job never runs

When we set the clocks forward:

02:00 → 03:00
Enter fullscreen mode Exit fullscreen mode

The cron job scheduled for 02:30 never runs.

⚠️ Cron doesn't have built-in daylight saving time (DST) support.

3. Anti-Patterns to Avoid

❌ Scheduling Business Logic Directly in Cron

0 9 * * * send_daily_report
Enter fullscreen mode Exit fullscreen mode

This assumes:

  • server time zone = company time zone
  • daylight saving time never changes
  • the environment is consistent

All assumptions are incorrect.

❌ Changing the server time zone for each application

timedatectl set-timezone Europe/Warsaw
Enter fullscreen mode Exit fullscreen mode

This breaks:

  • logs
  • monitoring
  • containers
  • multi-tenant servers

4. The Golden Rule (IT Standard)

Always run cron in UTC. Handling time zones in application code.

How they do it:

  • Cloud providers
  • Banks
  • SaaS platforms
  • Monitoring tools

Do it.

5. Correct architecture for time zone-safe cron jobs

✅ Step 1: Server and cron → UTC

timedatectl set-timezone UTC
Enter fullscreen mode Exit fullscreen mode

Cron:

* * * * * php bin/console cron:runner
Enter fullscreen mode Exit fullscreen mode

Cron runs frequently, not "on a schedule."

✅ Step 2: The application decides when to run

In your application:

$nowUtc = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$jobTime = new DateTimeImmutable('09:00', new DateTimeZone('Europa/Warszawa'));

if ($nowUtc->setTimezone($jobTime->getTimezone())->format('H:i') === '09:00') {
runJob();
}
Enter fullscreen mode Exit fullscreen mode

✔ Daylight Saving Time
✔ Predictable
✔ Testable

6. Store Schedules with Time Zone Metadata

Never store just cron_expression.

❌ Bad

{
"cron": "0 9 * * *"
}
Enter fullscreen mode Exit fullscreen mode

✅ Good

{
"cron": "0 9 * * *",
"timezone": "Europe/Warsaw"
}
Enter fullscreen mode Exit fullscreen mode

Your scheduler must:

  1. Convert now() → job timezone
  2. Run the cron job
  3. Run once
  4. Block execution

7. Idempotence: Protecting against duplicate executions

Daylight saving time or retries can still cause duplicates.

Always use execution locks:

UNIQUE(job_id, schedule_at)
Enter fullscreen mode Exit fullscreen mode

Or distributed locks:

  • Redis
  • Database lock

This guarantees: The job will run at most once on schedule.

8. Logging: Always log in UTC time

[2026-01-02T18:00:00Z] Job executed
Enter fullscreen mode Exit fullscreen mode

Convert only in the UI:

18:00 UTC → 19:00 CET
Enter fullscreen mode Exit fullscreen mode

This saves hours of debugging.

9. Monitoring and Alerting

Timezone errors are invisible without monitoring.

You should detect:

  • ❌ Task not executed
  • ❌ Task executed twice
  • ❌ Task executed late

And notify about it via:

  • Email
  • Slack/Discord

10. Checklist: Configuring cron for production

  • ✅ Server time zone = UTC
  • ✅ Application decides execution time
  • ✅ Time zone saved for each task
  • ✅ Logic for daylight saving time (DST)
  • ✅ Idempotent execution
  • ✅ UTC logs
  • ✅ Monitoring and alerting

Summary

Cron itself is inherently "dumb." This isn't a flaw—it's your responsibility as an engineer.

If your system:

  • Operates in multiple countries
  • Has users in different time zones
  • Performs critical tasks

➡️ Time zone-aware scheduling is not optional.


Want to monitor cron jobs and get notifications when they fail? Check out CronMonitor.app—simple monitoring that notifies you when something goes wrong.

Top comments (2)

Collapse
 
deltax profile image
deltax

This is exactly why scheduling should never be the decision layer.
Cron should wake the system.
The application should decide whether execution is justified at all.
Same principle applies to AI outputs.

Collapse
 
lmadev profile image
Łukasz Maśląg CronMonitor

Exactly! I agree 100%. Cron itself is, to put it mildly, "stupid" :)
A reliable trigger, but completely unaware of context.