Skip to main content

Free Cron Expression Builder

Build, validate, and explain cron expressions for scheduled tasks. Live plain-English description, next-5-runs preview, and common pattern presets.

Works offline once loaded
minute
(0-59)
hour
(0-23)
day
(1-31)
month
(1-12)
weekday
(0-7)

In plain English

At 9:00 AM, Monday through Friday.

Common patterns

Compatible with standard Unix cron, GitHub Actions, Kubernetes CronJob, and most scheduling systems. Use * for 'every', */5 for 'every 5', 1-5 for ranges, 1,15 for specific values. Also accepts @hourly, @daily, @weekly, @monthly, @yearly, and names like MON-FRI or JAN-DEC.

Common uses

  • Build Cron for GitHub Actions WorkflowsGitHub Actions uses cron syntax for scheduled workflows. Build and verify your schedule here.
  • Build Cron for Kubernetes CronJobsKubernetes CronJob resources use standard cron syntax. Build and explain the expression visually.
  • Build Cron Entries for Linux crontabBuild expressions for traditional Unix cron (cron, crontab -e) with confidence.
  • Schedule Database Maintenance JobsSchedule backup, vacuum, or analyze jobs with confidence using cron expressions.
  • Learn How Cron Expressions WorkEach tweak shows immediate plain-English explanation and a preview of the next 5 runs — best way to learn cron.

How It Works

The cron expression builder runs entirely in your browser using a hand-written parser in lib/cron.ts — no external library, no server call. It validates the expression, assembles a plain-English description using the browser's built-in Intl.DateTimeFormat and Intl.ListFormat APIs for locale-aware day and month names, and computes the next scheduled run times by walking forward through time with field-skipping logic rather than brute-forcing every minute.

  1. 1
    Expression parsed field-by-field
    The parser splits the expression into five (or six) whitespace-delimited fields and tokenizes each one for commas, ranges (e.g. 1-5), step notation (e.g. */15), and named values like MON or JAN. @macros such as @daily are expanded to their five-field equivalents before parsing begins. Invalid values or out-of-range numbers surface as typed error keys that map to localized messages.
  2. 2
    Human-readable description assembled
    describeCron() in lib/cron.ts builds the English (or localized) sentence by inspecting which fields are wildcards versus explicit sets. Day and month names are resolved through Intl.DateTimeFormat with the active locale, and list items are joined using Intl.ListFormat so the conjunction ('and' vs ',' vs locale-specific form) matches the user's language.
  3. 3
    Next run times computed with field skipping
    nextRuns() walks a Date object forward from the current moment, but skips entire months, days, or hours that cannot match rather than testing every minute. This means an impossible schedule like Feb 30 exits quickly through a five-year horizon check rather than looping 2.6 million times.
  4. 4
    Expression shared via the URL fragment
    Any expression you type is written to the page's URL fragment as #expr= (debounced 500 ms via window.history.replaceState). The fragment is never sent to a server; the page hydrates from it on load, so sharing or bookmarking a URL restores the exact expression without any server state.

Related Tools

Frequently Asked Questions