induwara.lk
induwara.lkDeveloper · Utility

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.

By Induwara AshinsanaUpdated May 11, 2026
Build a cron expressionPOSIX · 5-field

Every 15 minutes

Fields

Quick presets
Next 5 runslocal time
  1. Run 1· next
    Jul 03, 2026
    13:15 · Fri
  2. Run 2
    Jul 03, 2026
    13:30 · Fri
  3. Run 3
    Jul 03, 2026
    13:45 · Fri
  4. Run 4
    Jul 03, 2026
    14:00 · Fri
  5. Run 5
    Jul 03, 2026
    14:15 · Fri

Calculations follow the POSIX crontab specification and the Vixie cron(8) reference behaviour, including the OR rule when both day-of-month and day-of-week are restricted. Sources cited below.

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.

  1. 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.
  2. 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.
  3. 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.
  4. 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).
  5. Cross-check. The expression is formatted back to canonical cron syntax (preferring */N over a long list, A-B over 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

Every 15 minutes

*/15 * * * *

  1. Minute field */15 expands to {0, 15, 30, 45}
  2. Hour, day, month, day-of-week all *
  3. Description: "Every 15 minutes"
  4. From 09:07 → next 4 runs = 09:15, 09:30, 09:45, 10:00

Weekdays at 9 AM

0 9 * * 1-5

  1. Minute 0, hour 9, day-of-week range 1-5 = {Mon, Tue, Wed, Thu, Fri}
  2. Description: "At 9:00 AM, on Monday through Friday"
  3. From Friday 10:00 → next run = Monday 09:00 (skips Sat & Sun)
  4. Canonical form preserved: 0 9 * * 1-5

OR rule — day-of-month and day-of-week both set

0 12 1,15 * 1

  1. Minute 0, hour 12, day-of-month {1,15}, day-of-week {Mon}
  2. Both DOM and DOW restricted → Vixie OR rule applies
  3. Fires when DOM ∈ {1,15} OR DOW = Mon at noon
  4. In May 2026: 05-01 (1st, Fri), 05-04 (Mon), 05-11 (Mon), 05-15 (15th, Fri), 05-18 (Mon)
  5. Description ends with: "on day 1, 15 of the month OR on Monday"

Edge case — impossible date

0 0 31 4 *

  1. Minute 0, hour 0, day-of-month 31, month April
  2. April has 30 days, so day 31 in April never matches
  3. Forward walk advances month-by-month; April keeps failing the day check
  4. After 5 years with no match, scheduler reports "no run within 5 years"
  5. UI shows: "No run falls within the next 5 years. Check for impossible date combinations."

Frequently asked questions

Sources & references

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

Rate this tool
Be the first to rate

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.