Cron is how Unix-like systems schedule repeating jobs, and its expression format shows up far beyond crontab — in CI pipelines, Kubernetes CronJobs and cloud schedulers. The syntax looks cryptic at first, but it is just five fields separated by spaces.
The five fields
┌── minute (0–59)
│ ┌── hour (0–23)
│ │ ┌── day of month (1–31)
│ │ │ ┌── month (1–12)
│ │ │ │ ┌── day of week (0–7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *
Each field answers “at which values does this run?” A * means “every”. So * * * * * runs every single minute.
Syntax within a field
*— every value.5— exactly 5.1-5— a range, 1 through 5.*/15— a step: every 15th value (0, 15, 30, 45).1,15,30— a list of specific values.- Names —
JAN–DECfor months,SUN–SATfor weekdays.
Ready-to-use examples
| Expression | Meaning |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour, on the hour |
0 9 * * * | Every day at 09:00 |
0 9 * * 1-5 | Weekdays at 09:00 |
0 0 * * 0 | Every Sunday at midnight |
0 0 1 * * | The 1st of every month |
30 3 1 1 * | 03:30 on 1 January |
The one gotcha: day-of-month vs day-of-week
If both the day-of-month and day-of-week fields are restricted (not *), cron runs when either matches — not both. So 0 0 13 * 5 fires on the 13th and every Friday, not only on Friday the 13th. When in doubt, verify against real run times.
Check it before you ship it
The safest way to trust a cron is to see the actual times it will fire. The cron expression generator explains each field in plain language and lists the next run times in your local zone, with one-click presets. It all runs in your browser.
Related tools
- Converting Unix timestamps as well? Use the timestamp converter.
Shortcut strings
Most cron daemons accept named shortcuts in place of the five fields:
| Shortcut | Same as | Runs |
|---|---|---|
@yearly (or @annually) | 0 0 1 1 * | Once a year, 1 Jan |
@monthly | 0 0 1 * * | 1st of each month |
@weekly | 0 0 * * 0 | Every Sunday |
@daily (or @midnight) | 0 0 * * * | Every day at midnight |
@hourly | 0 * * * * | Every hour |
@reboot | — | Once at startup |
Also watch for field-count variants: Spring’s @Scheduled, Quartz and some cloud schedulers add a seconds field at the front (six fields), and AWS EventBridge uses a six-field form that forbids setting day-of-month and day-of-week together. A five-field expression dropped into a six-field parser is off by one field.
Time zones and daylight saving
Classic crontab has no time-zone field — it fires in the daemon’s local time. On Linux you can override that per file with a CRON_TZ=UTC line (or TZ); most cloud schedulers show a time-zone dropdown instead. For anything shared across regions, UTC is the safe default so nobody has to reason about offsets.
Daylight-saving switches are the classic trap. When clocks spring forward, a job set inside the skipped hour (say 30 2 * * *) may not run that day; when they fall back, a job in the repeated hour can run twice. Keep critical jobs outside the 01:00–03:00 window, or run them in UTC. If you also deal with epoch times, the complete guide to Unix timestamps covers how those map to wall-clock time.
Quick FAQ
- Can I combine ranges and steps? Yes —
0-30/10means 0, 10, 20, 30. - What does
*/2mean in the hour field? Every second hour: 0, 2, 4 … 22. - Does cron catch up on missed runs? No. If the machine is off at the scheduled time, plain cron skips it — use
anacronwhen catch-up matters.