Skip to content
Advertisement

Cron Expression Parser

Read a cron line in plain English, expand every field, and see the next ten firings in local time and UTC.

Decoder Reference

5 fields

Common schedules

Daemon timezone

In plain English

At 06:30, on Monday, Tuesday, Wednesday, Thursday and Friday.
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

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

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

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

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

All devops tools