Cron Expression Reference — All Five Fields, Steps, Names and @-Shortcuts

Every cron field explained — minute, hour, day-of-month, month, day-of-week — lists, ranges, steps, JAN–DEC/SUN–SAT names, ? and @-shortcuts.

Published 2026-09-25

A cron schedule is five fields and a command:

┌─────────── 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 both Sunday)
│ │ │ │ │
* * * * *  command to run

Each field independently filters time: the job fires when the current minute, hour, month, and the day rule all match. The day rule — how day-of-month and day-of-week combine — is the famous trap covered in its own article. Here’s every other field, precisely.

The four things every field accepts

syntax meaning example expansion (minute field)
* every allowed value 0–59
a a single value 30 → {30}
a,b,c a list 0,15,30,45 → {0,15,30,45}
a-b an inclusive range 9-17 → 9 through 17
*/n every n-th value */15 → {0,15,30,45}
a-b/n every n-th inside a range 2-30/5 → {2,7,12,17,22,27}
a/n start at a, step to the max 1/5 → {1,6,11,…,56}

A few details that bite in practice:

  • Steps count from the range start, not from 0. 2-30/5 gives 2, 7, 12 — not 5, 10, 15. */15 is shorthand for 0-59/15 (or the field’s real minimum — */2 in day-of-month starts at 1, not 0).
  • Ranges don’t wrap. 17-9 and fri-mon are invalid — cron wants low-to-high. To span a boundary, use a list: fri,sat,sun,mon or 22,23,0,1.
  • */0 is meaningless — a step of zero gets rejected.
  • Lists deduplicate silently. 5,5,5 is just {5} — harmless but a sign the line was machine-generated.

Month and day-of-week names

The last two fields accept three-letter English names, case-insensitive, anywhere a number would go:

0 9 * jan mon        09:00 on Mondays in January
0 0 * mar-jun fri    midnight on Fridays, March–June
0 8 * * mon,wed,fri  08:00 on Monday, Wednesday, Friday

mon in the minute field is an error — names live only in fields 4 and 5. Day-of-week numbers run 0 = Sunday through 6 = Saturday, with 7 as a second Sunday, so 5-7 is a legal Fri–Sun weekend span and 1-5 is the classic weekday range. SAT alone is 6; there’s no “weekend” keyword, you write 0,6 or sat,sun.

? — the Quartz-ism standard cron tolerates

In Quartz-derived schedulers (AWS EventBridge, Spring’s @Scheduled, some CI systems) one of the two day fields must be ? — “no specific value”. Standard cron doesn’t have the character at all; * already covers it. This calculator accepts ? in day-of-month and day-of-week as an alias for * so pasted Quartz expressions don’t silently change meaning — but if you’re writing a real crontab, use *.

What standard cron can’t say (and how Quartz does it)

Quartz syntax means standard cron equivalent
L in dom last day of month no syntax — guard with [ "$(date -d tomorrow +\%d)" = "01" ] on 28-31
5L in dow last Friday guard: [ "$(date -d '+7 days' +\%m)" != "$(date +\%m)" ] on 5
15W nearest weekday to the 15th no clean equivalent — compute outside cron
5#3 3rd Friday 0 0 15-21 * 5 + the weekday check below
0 0 * * * 2026 year field not supported — cron lines have no year

For “nth weekday”, the portable pattern is restricting the day-of-month to the only week it can fall in, then confirming the weekday in the command (necessary anyway because of the OR rule — see below):

# 3rd Friday of the month, 00:00 — fires only when both agree
0 0 15-21 * 5  [ "$(date +\%u)" -eq 5 ] && my-backup-job

The @-shortcuts

crontab also accepts seven nickname lines that replace all five fields:

shortcut expands to fires
@yearly, @annually 0 0 1 1 * Jan 1, 00:00
@monthly 0 0 1 * * 1st of each month, 00:00
@weekly 0 0 * * 0 Sundays, 00:00
@daily, @midnight 0 0 * * * every day, 00:00
@hourly 0 * * * * top of every hour
@reboot (none) once, when the cron daemon starts

@reboot is the odd one — it has no schedule and can’t appear with fields. It fires when cron starts (boot, or systemctl restart cron), which is why the calculator shows no “next runs” for it: there is no next time, there’s a next boot.

Field-by-field cheat sheet

field range names gotchas
minute 0–59 */n counts from 0
hour 0–23 24h clock; 0 is midnight, 12 noon
day of month 1–31 no 0; missing days (Feb 30/31) skip silently or never fire
month 1–12 JAN–DEC names case-insensitive
day of week 0–7 SUN–SAT 0 and 7 = Sunday; OR-combines with dom

Two closing reminders the calculator above enforces rather than assumes: a day-of-month that can’t exist in the selected months means the job never runs (0 0 31 2 *), and a schedule like 0 0 29 2 * runs but can wait four — or around non-leap century years like 2100, eight — years between firings.

Frequently asked questions

Is */15 the same as 0,15,30,45?

Yes — */15 expands to exactly those minutes. The two forms are interchangeable; */15 is just shorter. Same for */2 in the day-of-week field: it means days 0, 2, 4, 6 — Sun, Tue, Thu, Sat.

What does "1/5" mean (a number with a step but no range)?

Vixie cron reads it as 1-max/5 — start at 1 and step to the top of the field, so 1/5 in the minute field = 1, 6, 11, …, 56. Quartz's a/b means the same thing. If you want a bounded range, write it out: 1-30/5.

Can I mix names and numbers in one field?

Yes — jan,3,jul-sep and mon,wed-fri,0 are both legal. Names are case-insensitive and work inside lists and ranges, in the month and day-of-week fields only.

Is Sunday 0 or 7?

Both — standard cron accepts 0 and 7 for Sunday, including inside ranges (5-7 = Friday, Saturday, Sunday). 1 is always Monday. Be careful the other way: 0-6 covers a whole week, so */2 and 0-6/2 give the same days.

Why doesn't my "L" expression work in crontab?

L (last day / last weekday), W (nearest weekday) and # (nth weekday) are Quartz-scheduler extensions — standard 5-field cron has no syntax for any of them. Cronie will reject the line or ignore it, depending on version. Emulate them with a guard in the command — examples below.

What's the difference between @daily and @midnight?

Nothing — both expand to 0 0 * * *. The seven standard nicknames are @yearly/@annually, @monthly, @weekly, @daily/@midnight, @hourly and @reboot.