Cron Expression Builder
Build a five-field crontab expression with per-field inputs, see a plain-English description as you type, and preview the next five runs in your local time zone. POSIX-compatible, runs entirely in your browser.
How it works
The builder wraps three pure functions in lib/data/cron-expression-builder.ts: a parser that turns a five-field string (or a nickname like @daily) into a set of valid integers per field, a describer that turns that into a plain-English sentence, and a forward scheduler that walks the calendar to find the next runs. Nothing leaves your browser tab — open DevTools → Network if you want to verify.
- Tokenise. The input is normalised (whitespace collapsed, trimmed), then split on spaces into the five fields. If the user wrote a nickname —
@yearly,@monthly,@weekly,@daily,@hourly,@reboot— it is expanded to the equivalent five-field form from the standard table. - Parse each field. Within a field, commas separate list items. Each list item is one of: a single value, a hyphen range
A-B, a wildcard*, or any of those with a step suffix/N. Three-letter names (JAN…DEC, SUN…SAT) are accepted case-insensitively for the month and day-of-week fields. Bounds are checked per field: minute 0–59, hour 0–23, day 1–31, month 1–12, day-of-week 0–6 (with 7 also accepted for Sunday). Out-of-range values surface a specific error naming the field and the offending value — the parser never throws. - Describe. The describer walks the parsed sets and picks the shortest sentence form: a single minute and a single hour becomes “At 9:00 AM”; an arithmetic-progression minute set becomes “Every 15 minutes”; a contiguous day-of-week range becomes “Monday through Friday”; named values use full English (“January through March”). When both day-of-month and day-of-week are restricted, the sentence is explicit about the OR rule.
- Schedule the next runs.Starting from the next whole minute after “now,” the scheduler advances the cursor one field at a time: skip to the next valid month if the current month is out, then the next valid day, then the next valid hour, then the next valid minute. The day check enforces the Vixie OR rule — when both DOM and DOW are restricted, a day matches if either set contains it; when only one is restricted, that one decides. The walk has a five-year horizon, after which the schedule is treated as unreachable (catches mistakes like day 31 in April).
- Cross-check. The expression is formatted back to canonical cron syntax (preferring
*/Nover a long list,A-Bover comma-separated values for contiguous runs), then parsed a second time. The Verified badge stays green only when the two parses produce identical value sets per field — that catches any bug in the builder itself before you copy a wrong expression out of it.
The five-field grammar is POSIX-portable: it works in crontab on every Linux and BSD distribution, in systemd timers (via OnCalendar= after conversion), in Kubernetes CronJob manifests, in Vercel Cron, in GitHub Actions schedules, and in most cloud schedulers. Quartz (Java) and Spring Scheduler use a six- or seven-field grammar that prepends seconds — this builder does not generate those, on purpose, because POSIX cron and Quartz disagree on operators like ? and L.
Worked examples
Frequently asked questions
Sources & references
- POSIX crontab specification — IEEE Std 1003.1-2024
- crontab(5) man page — Vixie cron syntax and the DOM/DOW OR rule
- Wikipedia — Cron (history, nickname table, dialect comparison)
- Unicode CLDR — weekday and month name conventions used for descriptions
- Kubernetes CronJob — uses the same five-field POSIX cron syntax
The parser and the next-runs scheduler were last cross-checked against the cron(8) reference behaviour on 2026-05-11. The page is reviewed whenever a relevant POSIX revision lands or a widely-used scheduler (Kubernetes, GitHub Actions, Vercel Cron) changes its accepted dialect.
Related tools
Comments & feedback
Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.
Found a parsing edge case, a wrong next-run, or want a new preset?
Email me at [email protected] — most fixes ship within 24 hours.