Cron Expression Builder
Validate standard and Quartz cron expressions, read them in plain English, and see the next 10 fire times in any IANA timezone.
Privacy: Parsing and the fire-time calculation run in your browser, using the browser's own IANA timezone data. Your expression is never uploaded or logged.
At minute 0, 15, 30 and 45 past hour 9 through 17 on Monday through Friday.
Fields
| Field | Token | Matches |
|---|---|---|
| minute | */15 | 0, 15, 30 and 45 |
| hour | 9-17 | 9 through 17 |
| day-of-month | * | any day |
| month | * | every month |
| day-of-week | 1-5 | Monday through Friday |
Next 10 fire times
- Computing…
Fire times are wall-clock times in UTC, resolved with the browser's own IANA timezone database, and are computed locally — nothing is sent anywhere. Supported syntax: *, lists, ranges, steps (*/5, 9-17/2), three-letter month and day names, ? in Quartz, and the @daily-style macros. The Quartz modifiers L, W and # are rejected rather than guessed at.
What it does
Type a cron expression and get three things back: a field-by-field breakdown, a plain-English sentence, and the next ten times it will actually fire in a timezone you choose. Both dialects are supported — the 5-field crontab form and the 6- or 7-field Quartz form with seconds and an optional year. Preset buttons cover the schedules you write most often, and invalid expressions get a specific error naming the field and the allowed range rather than a generic “invalid cron”.
How it works
The parser is hand-written against the field semantics in the
POSIX crontab specification
and the
Quartz CronTrigger documentation.
It handles *, comma lists, ranges, steps in both the */5 and 9-17/2 forms,
three-letter month and day names, ? in the Quartz day fields, and the
@daily/@hourly/@weekly/@monthly/@yearly macros (which are expanded and
shown to you). @reboot is rejected on purpose: it is a startup hook, not a
schedule, so there is nothing to compute.
Fire times are calculated as wall-clock times, not by adding seconds to a
timestamp. The tool walks candidate calendar fields forward, tests each against
the parsed sets, and only then converts the matching local time to an instant
using the browser’s copy of the
IANA time zone database via
Intl.supportedValuesOf
and Intl.DateTimeFormat. That ordering matters, and it is how real schedulers
behave: cron matches the local clock, so a daily 02:30 job stays at 02:30 across
a daylight-saving transition instead of drifting to 01:30 or 03:30.
Everything runs in the page. The expression, dialect, and timezone are mirrored into the query string so a link carries the whole state.
The two things that page people at 3am
Day-of-month and day-of-week are ORed. If both fields are restricted, the
entry fires when either matches. 0 0 13 * 5 is not “Friday the 13th”, it is
“the 13th, plus every Friday” — roughly nine times more often than intended.
This is specified behavior, not a bug, and it is the single most common cron
mistake. Quartz avoids it by requiring ? in one of the two fields. If you
genuinely need AND, put the day check inside the job and exit early.
Timezone is not part of the expression. A crontab is interpreted in the
host’s timezone, which means the same file fires at different instants on
different machines. Kubernetes made this explicit: a
CronJob
without .spec.timeZone uses the timezone of the kube-controller-manager
process, wherever that happens to be running. AWS EventBridge is always UTC.
systemd timers take an optional zone on OnCalendar=. Set the selector here to
whatever will actually execute the job, not to your own timezone.
There is a third, quieter trap: steps do not wrap across the field boundary.
*/7 in the minute field gives 0, 7, 14, 21, 28, 35, 42, 49, 56 and then jumps
to minute 0 of the next hour, which is a four-minute gap. Any step that does not
divide its range evenly does this. If you need a true fixed interval, use a
scheduler with interval semantics rather than cron.
When to reach for it
Before you commit a CronJob manifest and discover the schedule empirically. When
you inherit a crontab and need to know what 0 3 * * 6 costs you on a Saturday.
When a job is firing more often than the expression suggests, and you want the
OR rule confirmed. When you are converting a Quartz schedule from a Java service
into a Kubernetes CronJob and need to strip the seconds field without shifting
the hour. And when someone asks “will this run over the DST change” — that
answer is in the fire-time list, with skipped candidates called out.
Related tools
- Timestamp converter for turning the fire times into Unix epochs and back.
- Kubernetes YAML linter for the CronJob manifest the expression is going into.
- YAML ↔ JSON converter when the schedule lives in a Helm values file.
- JSON formatter for the scheduler API response that reports the next run.
- Regex tester for grepping schedules out of a pile of crontabs.
Read the paired guide: Cron syntax explained.
Frequently asked questions
Why does my expression fire on days I did not ask for?+
0 0 13 * 5 means "the 13th or any Friday", not "Friday the 13th". This is specified behavior in POSIX and in Vixie cron: if either field is * the other one decides, but if both are restricted the entry runs when either matches. Quartz sidesteps the whole thing by requiring ? in one of the two fields. To get a true AND you need a day-of-week check inside the job itself.Which timezone does cron actually use?+
crond uses the system timezone of the host, so the same crontab fires at different UTC instants on a machine in UTC and one in Europe/Berlin. Kubernetes CronJob defaults to the kube-controller-manager's timezone and takes an explicit .spec.timeZone field; systemd timers take OnCalendar= with an optional zone; AWS EventBridge cron is always UTC. Pick the timezone here that matches whatever will actually run the job.What happens to a job scheduled inside a daylight-saving gap?+
30 2 * * * in America/New_York has no 02:30 on the spring-forward date, so the fire time is skipped — this tool marks those and tells you how many it dropped. On the autumn transition the local time occurs twice; most schedulers fire once, and this tool shows the post-transition instant. If a job must run exactly once per day, schedule it outside 01:00–03:00 local or run it on a UTC clock.How does Quartz differ from standard cron?+
0 0 12 * * ? is noon, not midnight. Quartz numbers day-of-week 1–7 with 1 = Sunday, while standard cron uses 0–6 with 0 = Sunday and accepts 7 as Sunday too — so 5 is Friday in Vixie cron and Thursday in Quartz. And Quartz requires ? in exactly one of day-of-month or day-of-week. Toggle the dialect switch before you trust the fire times.Why isn't <code>*/7 * * * *</code> every 7 minutes?+
*/7 in the minute field yields 0, 7, 14, 21, 28, 35, 42, 49, 56 — then the hour rolls over and the next fire is at minute 0, four minutes later. Any step that does not divide 60 evenly produces a short interval at the boundary. The same applies to */5 in the day-of-month field, where the month length varies. Note also that this tool accepts wrapping ranges such as 22-2; Vixie cron rejects those, so do not ship one to a Linux crontab.Related tools
Timestamp Converter
Convert Unix seconds, milliseconds, microseconds, and nanoseconds to ISO 8601 and human-readable dates in any IANA timezone, with a live clock.
Kubernetes YAML Linter
Paste a manifest and get severity-ranked findings: removed apiVersions, missing requests and probes, unpinned images, and permissive securityContext.
YAML ↔ JSON Converter
Convert YAML to JSON and back in your browser. Resolves anchors and merge keys, handles multi-document files, and lets you pick the output indent.
→ Read the full guide:How this tool actually works