Tools
Guides

Cron Expression Builder

Convert

Build, validate and explain cron expressions. Computes the next trigger time (UTC).

100% client-side No backend
Presets
Output
Next run (UTC)
—
Copy
—
On this page

What is a cron expression?#

A cron expression is a compact schedule written as five space-separated fields: minute hour day-of-month month day-of-week. A line like 0 9 * * 1-5 reads left to right as “at minute 0, hour 9, every day-of-month, every month, on days 1 through 5 (Monday–Friday)” — i.e. 09:00 on weekdays. Every * means “every value in this field”, so the more fields you pin down, the more specific the schedule; the more you leave as *, the more often it fires.

Cron is the native scheduling language of Linux crontab, GitHub Actions, Kubernetes CronJob, most CI systems, and countless task schedulers. Writing one correctly is half battle; the other half is the day-of-month / day-of-week quirk (see FAQ below) that trips up even experienced engineers. This page parses your five fields as you type, flags the exact field that has a syntax or range error, and computes the next run so you can confirm the schedule actually fires when you think it does.

How to use it#

  1. Edit the Expression box at the top. It boots with * * * * * (every minute).
  2. Below it sit five dropdowns — one per field (minute, hour, day-of-month, month, day-of-week). Each offers the common fragments for that field (*, */5, 0, 1-5, 0,6…); picking one drops it into the matching position of the expression, which is handy when you cannot remember whether */15 belongs in the minutes slot.
  3. The presets row fills in complete starter schedules in one click: every minute, hourly, daily, weekly, monthly, yearly, weekdays.
  4. The output panel shows Next run (the first instant at or after the current time that matches) and a status line that either confirms a valid parse or names the offending field. Hit now() to recompute against the current moment.

Key features#

  • Full five-field grammar. Supports *, comma lists (0,15,30,45), ranges (1-5), steps (*/15, 9-17/2), and month/day names (JAN-DEC, SUN-SAT, case-insensitive). 7 is accepted for Sunday and normalized to 0.
  • Correct day-of-month/day-of-week logic. Implements the standard Vixie-cron rule: when both fields are restricted, the job fires if either matches (logical OR); when only one is restricted, both must match (AND). Many naive calculators get this wrong.
  • Field-precise errors. A bad range or a stray letter is reported with the exact field at fault (minute, hour…), not a generic “invalid expression”.
  • UTC-based next-run. The next trigger is computed on the UTC components of the instant, so the result is deterministic regardless of where the page is loaded, then rendered as a normal date you can copy.
  • Unreachability guard. An expression that can never match (for example a day-of-month that no month contains) is detected rather than looping forever.

Worked example#

Type 0 9 * * 1-5 for a weekday standup. Field by field: minute 0, hour 9, day-of-month *, month *, day-of-week 1-5. Both the date field (*) and the weekday field (1-5) are restricted, but only the weekday is — the date is a wildcard — so the AND path applies: fire at 09:00 on days that are Monday through Friday. Next run shows the next upcoming weekday 09:00 UTC instant.

Now compare 0 0 1 * 1 — “minute 0, hour 0, the 1st of the month, every month, Monday”. Here both day-of-month (1) and day-of-week (1) are restricted, so cron takes the OR path: the job fires on the 1st of every month and on every Monday — not “Mondays that fall on the 1st”, which is the almost-universal misreading. The Next run panel makes the difference visible: you will see it tick over to the nearest Monday even when that Monday is not the 1st.

FAQ#

Why does my job fire on days I did not expect?#

Almost always the day-of-month/day-of-week interaction. Standard cron treats them as an OR when both are pinned: 0 0 1 * 1 means “the 1st, or any Monday”, not “the 1st only if it is a Monday”. If you want a job that runs only when the 1st is a Monday, cron itself cannot express that — you schedule the 1st and add a weekday check inside the script.

What do */5 and 9-17/2 mean?#

*/5 in the minutes field means “starting at 0, every 5th value” → 0, 5, 10, 15, …, 55. 9-17/2 means “within the range 9 to 17, every 2nd value” → 9, 11, 13, 15, 17 — useful for “every two hours during business hours”. The step divisor after / applies to whatever range or wildcard precedes it.

Is 0 or 7 Sunday?#

Both. The day-of-week field accepts 0 and 7 for Sunday (cron historically used 0; some systems added 7). This tool takes either and normalizes 7 to 0. Names work too: SUN, Mon, fri are all case-insensitive.

The expression parses but Next run looks far away. Is it wrong?#

Probably not — it usually means the schedule genuinely cannot fire soon. 0 0 29 2 * (Feb 29) is valid but matches only leap years, so the next run can be years away. The tool caps its search at roughly eight years; an expression that cannot match inside that window is reported as unreachable rather than hanging the page.