Skip to content
Control Plane Labs

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

FieldTokenMatches
minute*/150, 15, 30 and 45
hour9-179 through 17
day-of-month*any day
month*every month
day-of-week1-5Monday through Friday

Next 10 fire times

  1. 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.

Read the paired guide: Cron syntax explained.

Frequently asked questions

Why does my expression fire on days I did not ask for?+
Because day-of-month and day-of-week are ORed, not ANDed, when both are restricted. 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?+
Not the one you assumed. Classic 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?+
It does not run that day. 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?+
Three things bite. Quartz adds a leading seconds field, so the expression has 6 or 7 fields and 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?+
Steps are computed inside a single field's range, and the range restarts each hour. */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.

→ Read the full guide:How this tool actually works