Cron expression parser and builder
Translate a 5- or 6-field cron expression into plain English, validate every field, preview the next ten run times, and build a schedule from presets.
- Runs in your browser
- Nothing you enter is sent
- Free, no account
Shortcuts such as @daily, @hourly and @weekly are expanded automatically.
At 09:00, on Monday, Tuesday, Wednesday, Thursday and Friday.
Calculating…
| Field | Range | Notes |
|---|---|---|
| Second | 0-59 | Only in 6-field expressions (Quartz, Spring, node-cron) |
| Minute | 0-59 | — |
| Hour | 0-23 | 24-hour clock, 0 is midnight |
| Day of month | 1-31 | ? behaves like * |
| Month | 1-12 | JAN-DEC also accepted |
| Day of week | 0-7 | 0 and 7 are both Sunday; SUN-SAT also accepted |
| Syntax | Meaning |
|---|---|
| * | Every value the field allows |
| 5 | Exactly that value |
| 1,15,30 | A list — any of these values |
| 1-5 | An inclusive range |
| */15 | A step — every 15th value starting from the lowest |
| 10-40/5 | A step inside a range: 10, 15, 20 … 40 |
| MON-FRI | Three-letter day names, in the day-of-week field |
| JAN,JUL | Three-letter month names, in the month field |
| ? | Treated as * in the two day fields |
When both the day-of-month and the day-of-week field are restricted, classic Vixie cron runs the job when either matches, not both. 0 0 1 * MON therefore fires on the 1st of the month and on every Monday.
How to read and build a cron expression
- Type an expression, or start from a preset and adjust it.
- Each field also has its own box, so you can change just the hour without counting positions.
- The plain-English sentence updates live, and any error names the field that is wrong and why.
- Check the next ten run times before you deploy the schedule — the description and the actual behaviour can differ in ways that are easy to miss.
The fields
Standard crontab uses five fields. Quartz, Spring's scheduler and node-cron accept six, with seconds at the front. This tool detects which you have from the number of fields.
| Position (5-field) | Field | Range | Names accepted |
|---|---|---|---|
| — | Second (6-field only) | 0-59 | — |
| 1 | Minute | 0-59 | — |
| 2 | Hour | 0-23 | — |
| 3 | Day of month | 1-31 | — |
| 4 | Month | 1-12 | JAN-DEC |
| 5 | Day of week | 0-7 | SUN-SAT; both 0 and 7 mean Sunday |
Syntax within a field
| Syntax | Meaning | Example |
|---|---|---|
* | Every value | * * * * * — every minute |
5 | One value | 5 * * * * — five past every hour |
1,15,30 | A list | 0 1,13 * * * — 01:00 and 13:00 |
1-5 | An inclusive range | 0 9 * * 1-5 — 09:00 on weekdays |
*/15 | A step from the lowest value | */15 * * * * — :00, :15, :30, :45 |
10-40/5 | A step inside a range | 10, 15, 20 … 40 |
? | Treated as * in the two day fields | Quartz convention |
The day-of-month and day-of-week trap
This rule catches everyone at least once. When both the day-of-month and the day-of-week field
are restricted, classic Vixie cron runs the job when either matches — not when both do.
So 0 0 1 * MON fires on the first of every month and on every Monday, which is
roughly five times a month rather than the once you probably wanted.
To get an "and", restrict only one field in cron and check the other inside your job:
0 0 1-7 * * combined with a "is it Monday?" test at the top of the script gives you "the
first Monday of the month".
Shortcut keywords
| Shortcut | Equivalent |
|---|---|
@yearly, @annually | 0 0 1 1 * |
@monthly | 0 0 1 * * |
@weekly | 0 0 * * 0 |
@daily, @midnight | 0 0 * * * |
@hourly | 0 * * * * |
Steps do not mean "every N from now"
*/20 in the hour field means hours 0, 20 — and then it stops, because 40 is out of range.
It does not mean "every 20 hours". Any step that does not divide the field range evenly produces an
uneven gap at the wrap-around: */45 in the minute field fires at :00 and :45, then again
15 minutes later at :00. If you need a genuinely regular interval that is not a divisor of 60, use a
scheduler with interval support rather than cron.
Timezones and DST
The run times listed here are calculated in your device's timezone, which is shown above the table. A
cron daemon uses the system timezone, or the value of CRON_TZ if the crontab sets one —
and container images are very often UTC, which is the usual explanation for a job that fires "an hour
early".
Daylight-saving transitions are worth thinking about for anything scheduled between 01:00 and 03:00 local time: on the spring-forward day that hour does not exist, and on the autumn day it happens twice. Different cron implementations resolve this differently. Scheduling such jobs in UTC avoids the problem entirely.
What this parser does not support
The Quartz extensions L (last), W (nearest weekday) and # (nth
weekday of the month) are rejected with a clear message rather than silently mis-parsed, because their
semantics differ between implementations. Everything in the POSIX and Vixie grammar is supported.
Questions
Does it support 6-field cron with seconds?
Yes. Five fields are read as minute, hour, day-of-month, month, day-of-week. Six fields put seconds at the front, the convention used by Quartz, Spring and node-cron.
How are day-of-month and day-of-week combined?
With classic Vixie cron semantics: if both are restricted, a run happens when either matches, not both. The English description says so explicitly, because this rule surprises almost everyone.
Which timezone are the next run times in?
Your device local timezone, which is shown next to the list. A real cron daemon uses the server timezone or the CRON_TZ setting, so check that before trusting the preview for a production schedule.
Are @daily and @hourly shortcuts supported?
Yes — @yearly, @annually, @monthly, @weekly, @daily, @midnight and @hourly all expand to their standard five-field equivalents before parsing.
What syntax is accepted in each field?
Wildcards (*), lists (1,15), ranges (1-5), steps (*/15 and 0-30/5), three-letter month and day names, and ? treated as * in the day fields. Invalid ranges and out-of-bounds values are reported by field name.