Skip to main content
cron

Cron expressions: calculate the next run before trusting the schedule

Read cron fields left to right, test the next scheduled times in the target timezone, and avoid the day-of-month/day-of-week trap.

Thien Nguyen
By Thien Nguyen
Updated April 21, 2026 · 2 min read

Never ship a cron expression because it looks plausible. Calculate its next several runs in the same timezone and cron implementation that will execute it. The expression 0 9 * * 1-5 means weekday mornings in traditional five-field cron; it does not magically mean “business days in every locale”.

Read the five fields, then read the caveat

# minute hour day-of-month month day-of-week
  30     2      *       *       1-5

That is 02:30 Monday through Friday. It is not “every 30 minutes”; a leading 30 names one minute of the hour.

NeedExpressionSanity check
Every 15 minutes*/15 * * * *00, 15, 30, 45
Weekdays at 09:000 9 * * 1-5Monday to Friday only
First day each month0 0 1 * *Not the first weekday
Sunday at 23:4545 23 * * 0Confirm whether your cron accepts 0 or 7 for Sunday

The day fields are the footgun

In Vixie-style cron, when both day-of-month and day-of-week are restricted, a job may run when either matches. So 0 8 1 * 1 can run on the first of the month and every Monday—not only on Mondays that are the first.

“First business day” is a business rule, not a clean five-field cron expression. Schedule daily, then have code decide whether today qualifies.

Treat timezone and DST as input

Many crontabs run in the host's local timezone; containers and managed schedulers often default to UTC. Put the intended timezone next to the schedule, and choose what happens when a local time occurs twice or not at all during daylight-saving changes.

# Run in UTC; application converts reporting boundaries explicitly.
0 0 * * * /app/bin/daily-rollup

UTC is less surprising for infrastructure work. For payroll, local trading hours, or legal deadlines, use a scheduler that documents timezone and daylight-saving semantics rather than pretending the server clock is a policy engine.

Before enabling it

Generate at least ten future run times, including a month boundary and a DST boundary if relevant. Confirm overlap behaviour too: cron starts a new process even if yesterday's job is still running. A lock—database advisory lock, queue uniqueness key, or flock—is usually the missing half of the schedule.

Cron is excellent at saying when. Make the job itself responsible for deciding whether it is safe to run.

References

Primary documentation and specifications checked when this article was last updated.

cronautomationdevops

Related articles

All articles