Cron Expression Parser
Read a cron line in plain English, expand every field, and see the next ten firings in local time and UTC.
Common schedules
In plain English
- Minute
- 30
- Hour
- 6
- Day of month
- every value (1–31) *
- Month
- every value (1–12) *
- Day of week
- Monday, Tuesday, Wednesday, Thursday, Friday 1-5
Next 10 runs
— waiting for the clock. Run times are read from your browser after the page loads, so this page never ships a timestamp baked in at build time.
How Cron Expression Parser works
A cron expression is five whitespace-separated fields — minute, hour, day of month, month, day of week — and each one is a SET of permitted values, not a countdown. The daemon wakes once a minute and runs every job whose five sets all contain the current time. Nothing in the expression records when a job last ran, which is why cron has no concept of catching up after downtime.
Every field accepts the same handful of forms: a wildcard, a bare number, an inclusive range, a range with a step, a comma-separated list, and — in the month and weekday columns — three-letter names such as JAN or FRI. A step is a filter over the field’s own range rather than an interval between firings, so `*/15` in the minute column simply means {0, 15, 30, 45}. A job whose daemon restarted at 09:07 still fires at 09:15, not at 09:22.
The rule that catches almost everyone is how the two day columns combine. Day of month and day of week both select days, and Vixie cron resolves the clash by union: when NEITHER field is a wildcard, the job fires if EITHER one matches. `0 0 13 * FRI` means midnight on the 13th of any month AND midnight on any Friday — about 62 firings a year, not the twice-in-a-while that "Friday the 13th" suggests. The rule stays invisible for years because it only shows up once someone restricts both columns at once.
None of the five fields carries a timezone. The daemon interprets the expression in whatever local time its own process has, and a container image almost always has none configured, which means UTC. A `0 2 * * *` line written by someone in Berlin runs at 03:00 or 04:00 their time depending on the season. Daylight-saving transitions are worse: a job scheduled inside the hour that spring-forward skips does not run at all that day, and on the fall-back repeat some implementations run it twice.
Reference
- minute hour day-of-month month day-of-week
- minute 0–59 · hour 0–23 · day-of-month 1–31 · month 1–12 or JAN–DEC · day-of-week 0–6 or SUN–SAT (7 also means Sunday)
- Six-field (Quartz, Jenkins): seconds minute hour day-of-month month day-of-week
- a-b/s selects a, a+s, a+2s … while ≤ b · */s is shorthand for first-last/s
- @yearly 0 0 1 1 * · @monthly 0 0 1 * * · @weekly 0 0 * * 0 · @daily 0 0 * * * · @hourly 0 * * * *
How to use this tool
Drop in the expression
Five fields, or six if the line comes from Quartz or a Jenkins pipeline and carries a leading seconds column. Shorthand macros such as @daily are expanded to the fields they stand for.
Read the sentence it produces
The plain-English rendering is the fastest way to catch a transposed column — a schedule that reads "at minute 30 past hour 6" when you meant half past six in the evening.
Scan the per-field breakdown
Each column is expanded to the exact set of values it admits, so a range or a step that silently covers more or fewer values than intended is visible rather than inferred.
Compare the two clocks
Upcoming firings are listed in your own timezone beside UTC. If the two columns disagree by the amount that is about to break a maintenance window, that is the answer.
Worked examples
A quarter-hour schedule
- Given
- */15 * * * *
- Result
- Minutes 0, 15, 30 and 45 of every hour — 96 firings a day
The step counts from the start of the field, not from whenever the daemon started, so restarting the service does not shift the pattern.
Both day columns restricted
- Given
- 0 0 13 * FRI
- Result
- Midnight on the 13th, plus midnight on every Friday
The union rule at work. To express only "Friday the 13th" you need a wrapper script that checks the date and exits, because cron itself cannot intersect the two columns.
A date the calendar never reaches
- Given
- 0 0 30 2 *
- Result
- Never runs
February has no 30th, so the search is bounded at five years and reports honestly rather than spinning. A silent "no upcoming runs" would look identical to a parse failure.
Business-hours report in a UTC container
- Given
- 30 6 * * 1-5 with the reader in Europe/Paris
- Result
- 06:30 UTC Monday to Friday — 08:30 local in summer, 07:30 in winter
The shifting local time is the tell that the schedule was written against a wall clock the daemon does not share.
When to use it
- Checking a Kubernetes CronJob schedule before applying the manifest, where the controller uses UTC unless the spec sets an explicit timeZone.
- Reading an unfamiliar crontab mid-incident to work out whether a job was even due when the graph turned.
- Turning a requirement phrased in office hours into the line a container running UTC will actually honour.
- Confirming that a backup window and a report job do not both land on the same minute.
- Reviewing a pull request that changes a schedule, where the diff shows two numbers and nothing about what they mean.
Things to watch out for
- When both day columns are restricted the match is a union, not an intersection. This is the single most misread part of the syntax and it is inherited by anything that copies Vixie’s behaviour.
- A step wraps at the field boundary rather than carrying over, so `*/7` in the minute column fires at 0, 7, … 56 and then again at 0 — a four-minute gap across the hour, not seven.
- Quartz extensions — L for last, W for nearest weekday, # for nth-of-month, and ? — are rejected by name rather than guessed at. Silently misreading `0 0 L * ?` as a schedule that runs would be worse than declining it.
- Both 0 and 7 mean Sunday in the weekday column, which is why `0-7` and `*` cover the same set.
- @reboot has no time associated with it at all; it fires when the daemon starts, so no list of upcoming firings can be produced for it.
Frequently asked questions
Does 0 0 13 * FRI run only on Friday the 13th?
No — it runs on the 13th of every month and on every Friday, because Vixie cron takes the union of the two day columns whenever both are restricted. Getting only Friday the 13th requires a date check inside the job itself.
Which timezone does a cron schedule use?
Whichever one the daemon’s process is running in. Containers usually carry no zone configuration and default to UTC, so a schedule written against local office hours drifts by the UTC offset and shifts again at each daylight-saving transition.
What is the sixth field some cron lines have?
A leading seconds column, used by Quartz, Spring, and Jenkins but not by the traditional Unix daemon. Six-field and five-field lines look alike enough that pasting one into the other shifts every column by one position.
Why does */7 not fire every seven minutes?
Because the step filters the minute field’s own 0–59 range rather than measuring an interval. It admits 0, 7, 14 … 56, and then the next hour restarts at 0, leaving a four-minute gap that no seven-minute interval would produce.
What happens to a job scheduled during a daylight-saving jump?
A time inside the skipped spring-forward hour simply never occurs, so the job does not run that day. On the autumn repeat the same wall-clock hour happens twice, and whether the job fires once or twice depends on the daemon’s implementation.
Does cron catch up on jobs missed while a machine was off?
No. The expression describes matching times, not a queue of pending work, and nothing records the last successful run. Anything that must not be skipped needs a scheduler with its own state, or a job that reconciles from a timestamp it keeps.
Related DevOps tools
All devops tools- CIDR / Subnet Calculator Turn an IPv4 or IPv6 prefix into netmask, broadcast, usable range and host count — then split it, compare it, or aggregate a range.
- chmod / Unix Permissions Calculator Bind permission checkboxes, octal and symbolic modes together — including setuid, setgid, sticky and what a umask leaves behind.
- Uptime & SLA Calculator Convert an availability target into allowed downtime per day, month and year, track the error budget, and chain several services together.
- Kubernetes Resource Converter Convert CPU and memory quantities between every suffix Kubernetes accepts, and catch the ones that mean a billion times what you meant.
- YAML ↔ JSON Converter Convert either way with key order and comments-free fidelity, then see every scalar whose written form and parsed value disagree.
- .env File Converter Parse a dotenv file the way real readers do — quoting, escapes, comments — and retype it as JSON, YAML, docker flags, Compose, a Secret or a ConfigMap.