- Published on
Cron Expressions: Syntax, Examples, and Scheduling Notes
Read five-field cron expressions, compare common scheduler differences, and handle time zones and daylight saving deliberately.
- Authors

- Name
- Adam Johnston
- @admjski
Cron Expressions: Syntax, Examples, and Scheduling Notes
Cron expressions describe recurring times. The familiar five-field form is used by traditional Unix cron and many compatible schedulers, but providers add different fields, time-zone rules, and special characters. Treat an expression as belonging to a named implementation; verify it with that implementation before relying on it.
Read the five fields
A traditional five-field expression is:
minute hour day-of-month month day-of-week
| Field | Common values | Example meaning |
|---|---|---|
| Minute | 0–59 | 30 means minute 30 |
| Hour | 0–23 | 2 means 02:00 |
| Day of month | 1–31 | 1 means the first day of a month |
| Month | 1–12 or names | 1 means January |
| Day of week | commonly 0–6 or names; some cron variants also accept 7 for Sunday | 1-5 commonly means Monday through Friday |
The fields are separated by spaces. For example:
30 2 * * 1-5
On a conventional five-field cron, this means 02:30 on weekdays, using that scheduler's time zone. In a crontab file, the command follows the schedule:
30 2 * * 1-5 /usr/local/bin/backup.sh
The five fields alone are the schedule; the path and command are crontab syntax, not part of the cron expression. Use absolute paths because cron jobs often start with a limited environment and an unexpected working directory.
Build and check common schedules
The wildcard * means every valid value for that field. A comma lists values, a hyphen gives a range, and / gives a step. Examples:
| Schedule | Five-field expression | Notes |
|---|---|---|
| Every minute | * * * * * | Runs once per minute; minimum intervals vary by scheduler. |
| Every day at midnight | 0 0 * * * | Uses the scheduler's configured time zone. |
| At 05:30 on the first of each month | 30 5 1 * * | Day-of-month is restricted. |
| At 09:00 every weekday | 0 9 * * 1-5 | Day-of-week numbering varies; names can be clearer when supported. |
| Every 15 minutes during hours 09 through 17 | */15 9-17 * * * | Includes 17:00, 17:15, 17:30 and 17:45. |
Test the expression with the actual target scheduler or its official local simulator. A generic cron calculator may use different rules. There is no universal --test flag for cron libraries. For a Linux crontab, install it with crontab -e, list it with crontab -l, and inspect the command's own logs and exit behavior.
Day-of-month and day-of-week are a common trap
In many traditional Unix cron implementations, when both day-of-month and day-of-week are restricted (neither is *), a job runs when either field matches. For example:
0 9 1 * 1
may mean 09:00 on the first day of each month or every Monday, not only when the first falls on Monday. This behavior is implementation-specific. Quartz-style schedulers commonly use ? to leave one of those fields unspecified; do not copy that symbol into a five-field Unix crontab unless its implementation documents it.
Likewise, Sunday numbering and support for names or symbols such as L, W, and # differ. Check the target's syntax before using them. The Linux crontab manual describes the Linux field rules; Cloudflare Cron Triggers and AWS EventBridge Scheduler document their own formats.
Time zones and daylight saving
First decide whether the job should follow a wall clock (for example, 09:00 in London) or a fixed time worldwide (for example, 09:00 UTC). Then configure the scheduler explicitly where it supports a time zone:
- Linux cron variants may support a
CRON_TZsetting in the crontab.TZcan instead affect the command's environment; it does not universally set the schedule's time zone. node-cronevaluates in the system time zone by default and accepts atimezoneoption, such asUTCorEurope/London.- Cloudflare Workers Cron Triggers run on UTC.
- AWS EventBridge Scheduler accepts a time zone as part of the schedule configuration; its cron expression also has a year field and different day-field rules.
A local time can be skipped or repeated when daylight saving clocks change. The exact result depends on the scheduler. If a task must run exactly once at a fixed instant, prefer UTC or verify how the selected scheduler handles daylight-saving transitions. See the node-cron syntax and time-zone options before using its syntax.
Examples from different schedulers
Linux or macOS with traditional cron
Open the current user's crontab:
crontab -e
Add a command with an explicit executable path and redirect output if you need a simple log:
0 3 * * * /usr/bin/python3 /home/user/scripts/daily_report.py >> /home/user/logs/report.log 2>&1
This is 03:00 according to the cron daemon's time zone, not automatically UTC. Paths, shell and environment behavior can vary between systems.
Node.js with node-cron
node-cron supports five fields and an optional leading seconds field. Its seconds example is library syntax, not traditional crontab syntax:
import cron from 'node-cron'
cron.schedule(
'0 9 * * 1-5',
() => {
console.log('Weekday task')
},
{ timezone: 'UTC' }
)
This schedules the callback at 09:00 UTC on weekdays. It runs inside the Node.js process, so it will not run while that process is stopped. Use a process supervisor or managed scheduler when a job must survive application restarts.
Cloudflare Workers
Workers Cron Triggers use five fields and UTC. The schedule is attached to a Worker's scheduled() handler; it does not run a shell command. Follow the Workers documentation for configuration and local testing.
Troubleshoot deliberately
- Nothing runs: check the installed crontab, service status, executable permissions, absolute paths and command logs.
- It runs at the wrong local time: check the scheduler's configured zone and daylight-saving behavior; do not assume the shell's
TZchanges the schedule. - A month/day expression runs more often than expected: check how that implementation combines day-of-month and day-of-week.
- Runs overlap: cron usually starts a new invocation on schedule without knowing whether the previous one finished. Add a lock or use a scheduler with a documented no-overlap option if overlap would be harmful.
- A machine was off: traditional cron may miss that run. A catch-up service such as
anacronhas different behavior; consult the relevant system documentation.
A cron expression is only one part of reliable scheduling. Confirm the runtime, time zone, retry behavior and failure reporting for the system that will execute the work.
Further looks

