Skip to content

Cron Expression Parser

Parse a cron expression and see a plain-English description plus the next run times.

A cron parser does the opposite of a cron generator: paste in a five-field cron expression and get a plain-English description of when it fires. The tool above runs the parsing in your browser; nothing leaves your machine.

Why parsing is harder than it looks

A cron expression like */15 9-17 * * 1-5 looks simple. Reading it out loud needs:

  • Field-aware decoding. The minute field’s */15 is “every 15 minutes”; the hour field’s 9-17 is “9 AM through 5 PM”; the day-of-week field’s 1-5 is “Monday through Friday.”
  • Operator semantics. */N, ,, -, * each behave specifically. */15 is not the same as 15 (one is a step, the other is the literal value 15).
  • Edge case detection. */13 produces uneven intervals (the gap across the top of the hour is shorter). 0 0 31 * * fires only in months with a 31st. A list of upcoming run times makes both visible.
  • Day-of-month / day-of-week interaction. When both are restricted, Vixie cron ORs them. The tool above says so explicitly (”… OR … (either matches)”).

A naïve parser that just lists each field’s values gives technically correct output that’s hard to read. A good parser produces a sentence.

What the tool above outputs

Input:  0 17 * * 1-5
Output: Weekdays (Mon–Fri) at 5:00 PM

Input:  */15 9-17 * * 1-5
Output: Every 15 minutes, hours 9 through 17, on weekdays Mon through Fri

Input:  0 0 1,15 * *
Output: At midnight, on days of the month 1, 15

Input:  0 0 1 * 1
Output: At midnight, on day of the month 1 OR on weekday Mon (either matches)

Alongside the description it lists the next five run times (in your browser’s time zone) and which format it detected. For 0 0 31 * * the run list jumps from 31 October to 31 December, which is the quickest way to see that it skips shorter months.

Why you’d use a parser

  • Debugging an existing crontab. A schedule someone wrote a year ago that you’re now responsible for. Parse it before you change it.
  • Code review. A pull request adds 0 0 31 * * — does the author realize that doesn’t fire monthly? The parser surfaces the surprise.
  • Configuration migration. Moving from one scheduler to another (Vixie cron → systemd timers → AWS EventBridge). Parsing each schedule and re-encoding by hand catches incompatibilities.
  • Documentation. Generating human-readable schedule descriptions for runbooks.
  • Sanity check after generation. Build a cron expression with the generator, then parse it back to confirm it says what you meant.

What the parser doesn’t do

  • It doesn’t validate against every implementation. Cron flavors accept different extensions (L for last day, W for nearest weekday, # for nth weekday, H for hashed spread). The parser follows Vixie cron (names like MON-FRI, 7 for Sunday, steps inside ranges) and accepts Quartz’s 6/7-field form and ?; it rejects L, W, # and H with a message instead of guessing.
  • It doesn’t know your server’s time zone. Next run times are shown in your browser’s time zone; the cron daemon uses the server’s (often UTC).
  • @reboot has no schedule to describe. The other shortcuts — @yearly, @annually, @monthly, @weekly, @daily, @midnight, @hourly — are expanded to their five-field form.

The two cron flavors most parsers cover

Flavor5 fields6 fields (with seconds)Special chars
Unix / Vixie cronYesNo* / , -
QuartzNo (uses 6/7)YesAll Unix + L W ? #

Most parsers default to Unix cron. The tool above treats a 5-field expression as Unix cron and a 6- or 7-field one as Quartz (seconds first, optional year). Watch the day-of-week numbering: Quartz counts 1-7 from Sunday, Unix cron 0-6 (or 7) from Sunday.

Common parsing surprises

  • “Every 15 minutes” with */15 plus a constrained hour field. */15 9 * * * fires 9:00, 9:15, 9:30, 9:45 — only 4 fires per day, not 96. The hour field constrains the hour to 9 only.
  • Day-of-month + day-of-week is OR. 0 0 15 * 5 is “midnight on the 15th OR every Friday” — about 5–6 fires per month, not once. The tool above announces the OR explicitly.
  • 0 in the minute field with * in the hour. 0 * * * * is hourly (top of every hour). * 0 * * * is “every minute of midnight hour” — 60 fires once a day at midnight. The first field is the minute; the second is the hour.
  • Empty or invalid fields. Some parsers tolerate trailing whitespace and empty fields; some reject. The tool above names the field and the problem, e.g. “minute must be 0-59, got 61”.

Common pitfalls

  • Parsing without specifying the flavor. A Quartz expression has 6+ fields; parsing as 5-field cron will misalign all of them.
  • Trusting the parser’s natural-language output blindly. A parser saying “every 15 minutes, between 9 AM and 5 PM” is correct, but the spoken description doesn’t always make implementation issues (overlap, drift, DST) visible. The schedule is the description; the parser explains it but doesn’t validate it for production use.
  • Forgetting the timezone. “Midnight” in the description is the cron daemon’s local time. If the daemon is UTC and the description user is in Pacific, “midnight” means 4 PM PST. Document the assumed timezone alongside the description.

For the inverse — building a cron expression from a chosen schedule — see cron expression generator.