Interactive tool
Describe the schedule, get the line
Say when the job should run and this writes the expression — then reads it back with the same engine that explains one, so what you copy is what you were shown.
Runs in your browser · nothing is sent anywhere
0 2 * * *Runs at 02:00, every day.
Next five runs
Calculating from the current time…
Cron cannot express “the first Monday of the month”, or any other combination of a date and a weekday. When both the day-of-month and day-of-week fields are restricted it takes the union, not the intersection, so asking for both produces a schedule that runs far more often than intended. The way round it is to schedule the date range and test the weekday inside the job, exiting early when it does not match.
What a cron expression is
cron is the scheduler that runs jobs at set times on Unix-like systems, and a cron expression is the schedule written as five fields: minute hour day-of-month month day-of-week.
Reading one is a small skill. Writing one is where the mistakes happen, because a wrong expression is usually still a valid expression — the job runs, just not when you meant. Nothing errors, and you find out weeks later.
Using it
Choose how often, then the times or days. The expression appears with a plain-language read-back and its next five runs, so you can check the intent before committing the line.
The read-back is not written by this page. Whatever the controls produce is handed to the engine behind the explainer, and what you see is what that says — one interpreter, so the builder cannot describe a schedule differently from the tool that reads it back.
Warnings appear for choices that are legal but rarely intended: a step that does not divide 60, or a day of the month that some months do not have.
What cron cannot express
The union rule is the hard limit. When day-of-month and day-of-week are both restricted, cron ORs them rather than ANDing them, so “the first Monday of the month” cannot be written: 0 9 1-7 * 1 means the 1st to the 7th and every Monday. This builder never emits both, and the reason is stated on the page rather than hidden behind a disabled control.
There is also no notion of a missed run. If the machine is asleep or the job overruns its next slot, standard cron simply does not fire — there is no catch-up, and two copies can overlap if a run takes longer than the interval. anacron exists for the first problem and a lock file for the second.
Daylight saving is the other trap: in a non-UTC timezone, a daily job scheduled inside the shifted hour can run twice or not at all on the two changeover days. Scheduling in UTC removes it entirely, which is the main argument for doing so.
Tools that go with this
- Cron Expression ExplainerReads a five-field schedule in plain language and shows its next runs, with a warning about the day-of-month and day-of-week union rule.
- YAML and JSON ValidatorWhere the file breaks, in a sentence rather than "unexpected token" — with the line, the column, and conversion between the two formats.
Questions people ask about this
Can I schedule the first Monday of every month?
Not in standard cron, and this will not pretend otherwise.
When both the day-of-month and day-of-week fields are restricted, cron takes the union rather than the intersection. So 0 9 1-7 * 1 means “the 1st to the 7th, and also every Monday” — roughly eleven runs a month instead of one. The builder never emits an expression with both day fields set, for that reason.
The way round it is to schedule the date range and test the weekday inside the job, exiting early when it does not match. Some schedulers — Quartz, and Kubernetes via a wrapper — can express it directly; standard crontab cannot.
Why warn about a step like */7?
Because it does not mean “every 7 minutes”. The sequence restarts at zero each hour, so */7 fires at :00, :07 … :56, and then the next run is :00 — four minutes later, not seven. Any step that does not divide 60 has an uneven gap at the hour boundary. It is legal, it looks regular, and it is almost never what the author meant.
What happens if I pick the 31st?
The job runs seven times a year rather than twelve, because April, June, September and November have no 31st. cron does not roll the date back to the 30th — it simply never matches. The 30th skips February, and the 29th skips February in three years out of four. The builder says so when you choose one, because nothing else will: the schedule is valid and simply fires less often than expected.
Are the times in my timezone?
No — UTC. A crontab runs in the server's timezone, which is frequently not yours and frequently not UTC either, so showing them in your browser's zone would be actively misleading. Check the server with timedatectl, or set CRON_TZ at the top of the crontab to state it explicitly for the entries below.
How do I know the expression means what the page says?
Because the description is not written by the builder. Whatever the controls produce is handed to the same engine that powers the cron explainer, and the page shows what that engine says — including its next-run times. There is one interpreter, checked against croniter across 125 run times, so the thing you copy and the thing you were shown cannot disagree.
Did this get you to an answer?
No text box on purpose — please do not paste production logs anywhere