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.
What our tool says about the most common schedule. Type
0 9 * * 1-5into the cron generator and it reads the expression back field by field:Minute: 0 Hour: 9 Day of month: every Month: every Day of week: Mon-FriTwo things that trip people up are visible here. Day-of-month and day-of-week are both
every, and when both are unrestricted the schedule simply runs daily — but restricting both makes them behave as OR, not AND, which is the single most common cron bug. And1-5is Monday to Friday because the week starts at 0 = Sunday.
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 |
Every reading below came out of our own cron generator — it parses the five fields and says them back in words, which is the fastest way to catch a field you counted wrong.
| Expression | What our tool reads it as |
|---|---|
* * * * * | Minute: every Hour: every Day of month: every Month: every Day of week: every |
*/15 * * * * | Minute: every 15 Hour: every Day of month: every Month: every Day of week: every |
0 * * * * | Minute: 0 Hour: every Day of month: every Month: every Day of week: every |
0 9 * * 1-5 | Minute: 0 Hour: 9 Day of month: every Month: every Day of week: Mon-Fri |
30 3 * * 0 | Minute: 30 Hour: 3 Day of month: every Month: every Day of week: Sun |
0 0 1 * * | Minute: 0 Hour: 0 Day of month: 1 Month: every Day of week: every |
0 0 * * 1 | Minute: 0 Hour: 0 Day of month: every Month: every Day of week: Mon |
0 */2 * * * | Minute: 0 Hour: every 2 Day of month: every Month: every Day of week: every |
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.
The two expressions that trip everyone up are one character apart. 0 0 1 * * reads as Minute: 0 Hour: 0 Day of month: 1 Month: every Day of week: every — the first day of every month. 0 0 * * 1 reads as Minute: 0 Hour: 0 Day of month: every Month: every Day of week: Mon — every Monday. Field 3 is day-of-month and field 5 is day-of-week; setting both is an OR in most implementations, not an AND, so 0 0 1 * 1 fires on the 1st and every Monday.
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.