Coding

Cron Syntax Without the Cheat Sheet

Cron Syntax Without the Cheat Sheet

Cover: Cron Syntax Without the Cheat Sheet

Cron expressions look like line noise until you learn the one thing that makes them click: the order of the fields never changes, and you read them left to right, smallest unit to largest.

The five fields, in order

*     *     *     *     *
│     │     │     │     │
│     │     │     │     └─ day of week (0–6, Sunday = 0)
│     │     │     └─────── month (1–12)
│     │     └───────────── day of month (1–31)
│     └─────────────────── hour (0–23)
└───────────────────────── minute (0–59)

A bare * means "every value" for that field. So * * * * * means "every minute of every hour of every day" — it fires every single minute.

Reading real examples

  • 0 9 * * * — minute 0, hour 9, every day → 9:00 AM daily.
  • 0 9 * * 1-5 — same, but only Monday through Friday.
  • */15 * * * * — every 15 minutes, all day.
  • 0 0 1 * * — midnight on the 1st of every month.

The slash and comma tricks

*/N means "every N units" — */15 in the minute field is every 15 minutes. A comma lists specific values: 0 9,17 * * * runs at both 9 AM and 5 PM.

Reading order matters more than memorizing. Once you internalize minute → hour → day-of-month → month → day-of-week, you can read almost any expression without a reference — you're just asking "what value does each field allow?"

The one field that trips people up

If both day-of-month and day-of-week are restricted (not *), most cron implementations treat it as OR, not AND — the job runs if either condition matches. It's the single most common source of "why did this run on a day I didn't expect."

Comments