About Cron Expression Generator
A cron expression is five fields — minute, hour, day of month, month, day of week — and its reputation for being unreadable is mostly earned. The fields are positional with no labels, the ranges differ between them, and one rule behaves the opposite of how it reads.
That rule is worth stating plainly, because it causes real incidents. When both the day-of-month and the day-of-week field are restricted, cron runs when **either** matches, not when both do. So `0 0 1 * 1` does not mean “the 1st of the month, if it is a Monday” — it means “the 1st of the month, and also every Monday”, which fires around five times as often. When either field is `*` the behaviour is the intuitive one, which is exactly why the bug hides until someone sets both.
This tool spells that out in the description, warns when the rule is in play, and — more usefully than either — shows you the next six times the expression will actually fire. A list of real dates settles an argument that reading the syntax cannot.
The description and the schedule come from the same parse, deliberately. A tool that describes an expression with one code path and computes run times with another will eventually disagree with itself, and the person trusting the description is the one who gets paged.
How to build a cron expression
Start from a common schedule
Hourly, daily, weekdays at 9am. Most real jobs are a small edit away from one of these.
Edit the fields
Each field is labelled under the box with its valid range, so you can see which position you are changing.
Read the description
Plain English, including an explicit warning when the day fields are being ORed.
Check the next runs
Six real dates and times. If they are not what you expected, the expression is wrong regardless of how it reads.
The syntax, in full
- * — every value in the field.
- 5 — exactly that value.
- 1-5 — an inclusive range.
- 1,3,5 — a list.
- */15 — every 15th value, starting at the field's minimum.
- 9-17/2 — every 2nd value within a range.
- JAN–DEC and SUN–SAT — names, accepted in the month and day-of-week fields.
- @daily, @hourly, @weekly, @monthly, @yearly — shorthands every implementation accepts.
Things that catch people out
- Both day fields set means OR, not AND. This is the big one.
- Sunday is both 0 and 7. Either works, and mixing them in one list is legal but confusing.
- Six fields is not standard cron. Quartz and systemd add a seconds field at the front; pasting one into crontab fails.
- Cron uses the server's time zone, usually UTC. A job set for 09:00 will not run at 09:00 your time unless the machine agrees.
- */7 does not mean “every 7 minutes” across the hour boundary. It fires at 0, 7, 14 … 56, then again at 0 — a 4-minute gap at the top of every hour.
- A valid expression can still never fire. 30 February parses perfectly and never happens.