Skip to content
K Knidox Search…
Computer Science · Scheduling

Cron Expression Parser

Translate a cron expression into plain English, and see exactly when it next runs.

Five fields: minute, hour, day of month, month, day of week.
Common schedules
What it means
At 09:30 on Monday, Tuesday, Wednesday, Thursday and Friday.

Read in the server’s local time zone, which is often UTC.

Field breakdown
FieldMatches
minute30
hour9
day of monthevery (1–31)
monthevery (1–12)
day of week1, 2, 3, 4, 5

Next-run times use your browser’s time zone. A server almost always runs on UTC, so the actual firing times will differ unless you are on UTC yourself.

A cron expression has five fields: minute, hour, day of month, month, and day of week. So 30 9 * * 1-5 reads as 09:30 on Monday through Friday, and */15 * * * * means every fifteen minutes.

Five fields, read left to right

Cron schedules are compact to the point of being cryptic, but the structure is simple: five space-separated fields, each describing one unit of time, from the smallest to the largest. A field matches either everything (*) or a specific set of values.

The syntax within a field is where the expressiveness comes from. A list (1,15) matches several values. A range (1-5) matches everything between two. A step (*/15) matches every nth value, and steps can be applied to ranges too — 9-17/4 gives 9, 13, and 17.

The trap in the two day fields

Cron has two ways to specify days: day of month and day of week. When both are restricted, cron does not require both to match — it runs when either does. So 0 0 1 * 1 fires on the first of the month and on every Monday, not only on Mondays that fall on the first.

This surprises almost everyone, because every other field is combined with AND. It is a genuine quirk of the original implementation, preserved for compatibility, and this parser flags it when both fields are set.

┌ minute (0–59) ┌ hour (0–23) ┌ day of month (1–31) ┌ month (1–12) ┌ day of week (0–6, 0 = Sunday) * * * * *

Within any field: * matches all, a,b lists values, a-b gives a range, */n steps, and a-b/n steps within a range. Month and weekday names such as JAN and MON also work.

Reading an expression

Take 30 9 * * 1-5 field by field:

  1. 1
    Minute: 30. The job runs at 30 minutes past the hour — not every minute.
  2. 2
    Hour: 9. Only during the 9 o’clock hour, so 09:30 rather than half past every hour.
  3. 3
    Day of month: *. Any day of the month — this field imposes no restriction.
  4. 4
    Month: *. Every month.
  5. 5
    Day of week: 1-5. Monday through Friday. Zero is Sunday, so 1–5 is the working week.
  6. 6
    Put it together. At 09:30, Monday to Friday — a weekday-morning job.

Common schedules

The patterns that cover most real scheduling needs.

ExpressionMeaning
* * * * *Every minute
*/5 * * * *Every five minutes
0 * * * *Every hour, on the hour
0 3 * * *Daily at 03:00
30 9 * * 1-5Weekdays at 09:30
0 0 * * 0Weekly, Sunday at midnight
0 0 1 * *Monthly, on the 1st at midnight
0 0 1 1 *Yearly, on 1 January
0 9-17/4 * * *At 09:00, 13:00, and 17:00

Time zones and portability

Cron runs in the server's local time zone, which on most infrastructure is UTC. A schedule that looks like a sensible 09:00 start can therefore fire in the middle of the night for the team reading its output. The next-run times shown here use your browser's zone, so compare them against what the server is actually set to.

Daylight saving adds a further wrinkle on servers that do use a local zone: when clocks go forward, a job scheduled inside the skipped hour may not run at all, and when they go back it may run twice. Scheduling outside the 01:00–03:00 window avoids the problem entirely.

One portability note. Some schedulers — notably Quartz, used in the Java ecosystem — extend the syntax with ?, L, W, and #, and add a seconds field at the front. Those are not standard cron, so this parser rejects them rather than guessing: an expression that means one thing in Quartz and another in Unix cron is worse than one that fails loudly.

Why does my job run on days I did not expect?
Almost certainly the day-of-month and day-of-week trap. When both fields are restricted, cron runs when either matches, not both — so 0 0 1 * 1 fires on the 1st and on every Monday.
What time zone does cron use?
The server’s local time zone, which is usually UTC. The next-run times here use your browser’s zone, so check what the server is set to before relying on them.
What does */15 mean?
Every fifteenth value in that field, starting at its minimum. In the minute field that gives 0, 15, 30, and 45 — so the job runs four times an hour.
Is Sunday 0 or 7?
Both are accepted by most implementations, and this parser treats 7 as Sunday too. Zero is the more portable choice, since not every cron accepts 7.
Can I schedule something every 90 minutes?
Not with a single expression, because steps restart each hour. The usual workaround is two entries, or a schedule at fixed times such as 0 0,3,6,9,12,15,18,21 * * *.
Why are ?, L, and W rejected?
They are Quartz extensions rather than standard cron. Accepting them would produce a description that does not match what a Unix cron would actually run, so failing loudly is safer.
What happens during daylight saving changes?
On a server using a local time zone, a job in the skipped hour may not run when clocks go forward, and may run twice when they go back. Scheduling outside 01:00–03:00 avoids it.