Skip to main content
Part ofCitedFigures.See the family
Dev Utilities Pro

Cron Expression Builder & Validator

Validate a standard 5-field cron expression (minute hour day-of-month month day-of-week), translate it to plain English, and see the next 5 run times — all computed in UTC. Supports *, lists (,), ranges (-), and steps (/ and */n), with day-of-week 0-6 (0 = Sunday; 7 is also accepted as Sunday). The next-run scheduler honors cron's day-of-month/day-of-week OR rule: when BOTH the day-of-month and day-of-week fields are restricted, a run fires when EITHER matches — the standard Vixie-cron behavior most people get wrong. Primary sources: the POSIX crontab specification (IEEE Std 1003.1 / The Open Group) and man 5 crontab (Vixie cron, Paul Vixie, 1988).

Cron expression (5 fields, UTC)

Order: minute hour day-of-month month day-of-week. Tokens: * (all), lists ,, ranges -, steps / and */n. Day-of-week 0–6 (0 = Sunday; 7 also accepted).

Validity
Valid
At 09:00, on Monday
Plain English

At 09:00, on Monday

Field breakdown
FieldRangeAllowed values
Minute0-590
Hour0-239
Day of month1-31every value
Month1-12every value
Day of week0-6 (0=Sun)Mon
Next 5 run times (UTC)
  1. 2026-07-13T09:00:00.000Z#1 · Mon, Jul 13, 2026, 09:00 UTC
  2. 2026-07-20T09:00:00.000Z#2 · Mon, Jul 20, 2026, 09:00 UTC
  3. 2026-07-27T09:00:00.000Z#3 · Mon, Jul 27, 2026, 09:00 UTC
  4. 2026-08-03T09:00:00.000Z#4 · Mon, Aug 03, 2026, 09:00 UTC
  5. 2026-08-10T09:00:00.000Z#5 · Mon, Aug 10, 2026, 09:00 UTC

Computed from the current time, strictly after now, in UTC. Real cron daemons run in the crontab owner’s timezone — run servers in UTC to keep schedules unambiguous.

Advertisement

View the TypeScript implementation on GitHub: packages/calc/src/cron-expression.ts · view tests

What this means

Cron is deceptively simple: five numbers and a few wildcards. The trouble is that two of its rules quietly violate the intuition almost everyone brings to it. The first is the day-of-month / day-of-week OR rule. When both day fields are restricted, cron fires when either matches — so 0 0 1 * 1 runs on the 1st of every month and on every Monday, not 1st-only-when-Monday. The man page states it plainly, but the expression reads like an AND, and that mismatch ships bugs.

The second trap is time. A cron expression has no timezone of its own — it inherits the crontab owner’s timezone (or CRON_TZ), which means the same five tokens fire at different absolute instants on different machines, and twice (or not at all) across a Daylight Saving Time transition. This tool sidesteps both issues by computing everything in UTC and applying the OR rule exactly as Vixie cron does, so the schedule you see is the schedule you get.

In my experience the bugs that survive code review are almost never typos in the minute field — they’re the OR-rule surprise and the “why did my job run at 6 a.m. instead of 1 a.m.?” timezone drift. I’ve seen a nightly billing job double-fire for a year because someone wrote 0 0 1 * 1meaning “first business day” and cron read it as “1st OR Monday.” And I’ve found that the */n step is the other quiet offender: */40in the minute field gives you 0 and 40, then jumps back to 0 — a 20-minute gap chasing a 40-minute gap, not the even spacing the slash implies. The fix is always the same: expand the field, look at the actual value set, and read the next few real run times before you deploy.

Worked example

Take 0 9 * * 1. Field by field: minute = 0, hour = 9, day-of-month = * (every day), month = * (every month), day-of-week = 1 (Monday). Because day-of-month is *and only day-of-week is restricted, the OR rule does not apply — the schedule is simply “09:00 on Mondays.”

Now the next runs. Suppose the reference instant is 2026-01-01T00:00:00Z, a Thursday. The scan starts at the next minute and walks forward until it hits a Monday at 09:00. The first match is 2026-01-05T09:00:00Z (the first Monday on or after Jan 1), then 2026-01-12T09:00:00Z, then 2026-01-19T09:00:00Z— each exactly seven days apart, all at 09:00 UTC.

Contrast that with the OR-rule case 0 0 1 * 0 (midnight, day-of-month 1, day-of-week 0 = Sunday). Both day fields are restricted, so it fires on the 1st of the month or any Sunday. From the same 2026-01-01T00:00:00Z reference, the next five matches are 2026-01-04, 2026-01-11, 2026-01-18, 2026-01-25 (the Sundays in January), then 2026-02-01(the 1st — which happens to also be a Sunday in 2026), every one at 00:00:00Z. That spread of dates is the OR rule made visible: a schedule far busier than “midnight on the 1st” alone.

Advertisement

Frequently asked questions

See the methodology — how this tool is built (TypeScript + Vitest), sourced (POSIX crontab spec, man 5 crontab / Vixie cron), and reviewed.

By Last verified against POSIX crontab specification (IEEE Std 1003.1) + man 5 crontab (Vixie cron)

Founder & Editor, Bedrocka Tools

The information and tools on this website are for general educational purposes only and do not constitute financial, investment, legal, or tax advice. Consult a licensed professional for decisions specific to your situation.