Cron Expression Parser

Parse and explain cron expressions in plain English. See next 5 run times with preset shortcuts.

Cron Expression

Presets

Field Breakdown
Minutes0
Hours9
Day of monthevery day
Monthevery month
WeekdayMonday, Tuesday, Wednesday, Thursday, Friday
Next 5 Run Times
Calculating...

Paste a cron expression and this breaks it into a field-by-field English description plus the next five run times, computed in your browser's local timezone. It accepts both the standard 5-field format (minute hour day month weekday) and the 6-field variant with a leading seconds field used by Quartz and Spring's @Scheduled.

Supported syntax, exactly

Each field takes *, plain numbers, ranges (1-5), comma lists (0,30), and steps in two forms: */15 or a bounded range like 10-40/10 (which yields 10, 20, 30, 40). A bare number with a step, like 5/2, is rejected — write 5-59/2 if you mean "every 2 starting at 5". Out-of-range values name the failing field: a minutes value of 60 reports "Invalid minutes field (range 0-59)".

Not supported: name aliases (MON, JAN — use 1), the Quartz specials L, W, # and ?, and @-macros as typed input — entering @daily fails with "Expected 5 or 6 fields, got 1". The presets cover the same ground numerically; the @daily button inserts 0 0 * * *.

Two things the next-run preview does differently from your server

First, timezone: the five timestamps are computed from your browser clock. If your server runs cron in UTC — most containers do — the real fire times shift by your UTC offset, the most common reason a job "runs at the wrong time". Second, resolution: in 6-field expressions the seconds field is validated and described, but the run-time preview evaluates at whole-minute resolution, so */10 in seconds shows one entry per matching minute rather than six.

Business-hours polling
Input: */15 9-17 * * *
Output: Minutes: every 15 minutes; Hours: 9, 10, 11, 12, 13, 14, 15, 16, 17 — runs at :00, :15, :30, :45 of each listed hour, 36 times per day from 09:00 through 17:45
The hour range is inclusive on both ends, so the 17:00-17:45 runs are easy to forget when you meant "until 5pm".
Weekday mornings
Input: 0 9 * * 1-5
Output: Minutes: 0; Hours: 9; Weekday: Monday, Tuesday, Wednesday, Thursday, Friday — entered on Sunday, Aug 9, 2026, the first listed run is Mon, Aug 10, 2026, 09:00:00 AM
Weekdays accept 0-7, and both 0 and 7 mean Sunday — the run-time engine normalizes 7 to 0.
Day-of-month OR day-of-week
Input: 0 0 1 * 1
Output: Minutes: 0; Hours: 0; Day of month: 1; Weekday: Monday — the next-run list interleaves the 1st of each month with every Monday
When both day fields are restricted, cron fires when either matches — not both. This surprises nearly everyone.

Questions people ask

I set day-of-month 1 and weekday 1 to get "first Monday". Why does it fire every Monday?

Because when both fields are restricted, standard (Vixie) cron treats them as OR — the job fires on the 1st of the month and on every Monday — and this preview models the same rule. Cron has no native "first Monday" syntax. Schedule 0 0 1-7 * * instead and let the command check the weekday: [ "$(date +\%u)" = 1 ] && your-job (% must be escaped in a crontab). Quartz's MON#1 covers this, but neither standard cron nor this parser accepts it.

Why don't the run times match what my server logs show?

Almost always timezone. This preview uses your browser's local time, while crond typically evaluates the expression in the server's timezone, often UTC. A 0 9 * * * job on a UTC server fires at 9:00 UTC regardless of what this page displays.

The timestamp converter translates the epoch values in your scheduler's logs into readable dates, and the date difference calculator helps sanity-check the gap between two observed runs.

Further reading