The five fields
┌───────────── minute (0–59)
│ ┌─────────── hour (0–23)
│ │ ┌───────── day of month (1–31)
│ │ │ ┌─────── month (1–12 or jan–dec)
│ │ │ │ ┌───── day of week (0–7 or sun–sat, 0 and 7 are Sunday)
│ │ │ │ │
* * * * *
A job runs when every field matches the current time, with one exception (below) that catches almost everyone out.
Special characters
| Symbol | Means | Example |
|---|---|---|
* |
Every value | * * * * *: every minute |
, |
A list | 0 9,17 * * *: 09:00 and 17:00 |
- |
A range | 0 9-17 * * *: every hour from 09:00 to 17:00 |
/ |
A step | */15 * * * *: every 15 minutes |
| names | Months and days | 0 0 * * mon |
Steps combine with ranges: 0 9-17/2 * * * runs every two hours between 9 and 17. A step on * starts at the field’s lowest value, so */20 in the minute field means 0, 20 and 40, not “20 minutes from now”.
The day trap
This is the one that causes real incidents.
When both the day-of-month and day-of-week fields are restricted, cron runs the job when either matches. They’re an OR, not an AND.
0 0 1 * 1 doesn’t mean “the first Monday of the month”. It means midnight on the 1st and midnight every Monday: roughly five times as often as intended.
If one of the two fields is *, the rule doesn’t apply and the other simply decides. That’s why “the first Monday” can’t be written in standard cron at all: you run it every Monday and check the date inside the job.
Macros
| Macro | Same as |
|---|---|
@yearly, @annually |
0 0 1 1 * |
@monthly |
0 0 1 * * |
@weekly |
0 0 * * 0 |
@daily, @midnight |
0 0 * * * |
@hourly |
0 * * * * |
@reboot is different: it runs when the machine starts, so there’s no schedule to predict.
Six fields, with seconds
Standard crontab has five fields. Spring, Quartz and a few other schedulers add seconds at the front, so 0 */5 * * * * there means “every five minutes”, while the same line in crontab is an error. Paste either form here: the field table shows which one was read, so you can tell at a glance whether you’re looking at a five- or six-field expression.
Timezones and daylight saving
A cron job runs in the timezone of the machine running it, which for a container is very often UTC. That’s why a “09:00” job can fire at what feels like the middle of the night.
Daylight saving adds two edge cases on the days the clocks change: a job scheduled in the missing hour may not run at all, and one in the repeated hour may run twice. Jobs that must happen exactly once are safer scheduled in UTC, or made safe to run twice.