Classic cron expressions use exactly five space-separated fields — minute (0–59), hour (0–23), day-of-month (1–31), month (1–12), and day-of-week (0–7, with both 0 and 7 meaning Sunday) — and they accept only five kinds of syntax tokens: numeric values, the asterisk wildcard, comma-separated lists, inclusive ranges, and positive integer steps applied to a wildcard or range. Anything else — names like JAN or MON, nicknames like @daily, question marks, seconds, year fields, or hashed schedules — belongs to a different scheduler dialect and is rejected by a strict classic parser. The compactness hides mistakes: a single field in the wrong position can move a task from every hour to every day, and a valid-looking day rule can match on a different calendar boundary than expected. A reliable cron parser cheat sheet therefore has to cover both the field ranges and the OR behavior between day-of-month and day-of-week, because traditional crontab matches when either restricted day field matches rather than requiring both. This guide walks through that field-by-field, then shows how to verify any expression you write before it reaches a production scheduler.

Cron Field Syntax at a Glance
A classic crontab line is exactly five fields, separated by single spaces, read left to right. The position defines what the value means, so swapping two fields silently changes the schedule. Minute and hour together pin the time of day: * 9 * * * fires every minute from 09:00 through 09:59 because the hour field is restricted to 9 and the minute field runs through every minute 0–59. The table below captures the conventional numeric ranges used by Cronie-style crontab files and accepted by the Cron Parser.
| Position | Field | Allowed Values | Notes |
|---|---|---|---|
| 1 | Minute | 0–59 | When the job fires inside the hour |
| 2 | Hour | 0–23 | 24-hour clock; 0 is midnight |
| 3 | Day of month | 1–31 | Calendar validity handled by JavaScript Date; month-end is skipped automatically |
| 4 | Month | 1–12 | Numeric only; JAN, FEB, and so on are not accepted |
| 5 | Day of week | 0–7 | 0 and 7 are both normalized to Sunday |
Day-of-month and day-of-week are the two ways to talk about calendar days, and the OR rule described below means you rarely want to restrict both at once. Month accepts only 1 through 12; expressions like * * * jan-may * are not part of the classic grammar and are rejected. Any field outside its allowed range, an empty list item, a descending range such as 5-3, a step of zero, or extra command text after the fifth field is rejected with a focused error message rather than silently ignored.
Special Characters: *, ,, -, and /
The classic format recognizes four special characters. Each one is a building block; combining them lets you describe most schedules without leaving numeric syntax.
- * (asterisk) — the wildcard means "every valid value in this field". * * * * * therefore fires every minute.
- , (comma) — a list separator. 0,15,30,45 * * * * fires at quarter past, half past, and quarter to every hour.
- - (hyphen) — an inclusive numeric range. 8-12 in the hour field means 8, 9, 10, 11, and 12.
- / (slash) — a positive integer step applied to a wildcard or a range. */10 selects every tenth value starting at the field minimum, while 10-50/20 selects 10, 30, and 50.
If you need to fire at 00, 15, 30, and 45 minutes past the hour, three syntaxes describe the same schedule: */15, 0,15,30,45, 0-45/15, and the equivalent step form. The first two are the most readable. When you mix individual values with a step-restricted range, remember the comma is just a separator: 0,30-50/10 parses as 0 plus 30, 40, and 50, not as 0 plus the entire 30-50/10 progression. Whitespace between tokens is normalized during validation, so extra spaces inside a field do not change the meaning.
How to Validate a Five-Field Expression with the Cron Parser
The parser enforces the rules above before it ever tries to compute the next runs. Use it as a final check whenever you hand-write a crontab line, especially for a job that fires only once a day.
- Enter exactly five fields in the minute, hour, day-of-month, month, and day-of-week order. A leading or trailing field, or a sixth field for a command, is rejected.
- Use numeric values, the * wildcard, comma lists, inclusive ranges, or steps such as */15. Names, nicknames, question marks, year fields, and seconds are not part of the classic format.
- Read the normalized expression, the per-field summary, and the next five matching instants shown in your browser's local time alongside their ISO UTC timestamps.
- Confirm the expression against the documentation and configured time zone of the scheduler that will actually execute the job, because the parser does not change which clock the scheduler uses.
If your scheduler is Quartz, Kubernetes CronJob, a cloud cron service, or any product that adds seconds, years, or weekday nicknames, a valid five-field expression may mean something different there or be rejected outright. The Cronie crontab(5) source documents the canonical numeric grammar, and the Oracle Linux cron guide summarizes the day-field OR semantics in a vendor-neutral way. Treat the parser as a syntax check and a numeric verification aid; the deployment environment still controls what time the job actually fires.
Day-of-Month and Day-of-Week OR Semantics
The day fields are the single biggest source of cron confusion. Traditional crontab does not require both fields to match — when both day-of-month and day-of-week are restricted, a candidate time matches if either restricted field matches.
Consider 0 0 21 * 1. Restricting day-of-month to 21 and day-of-week to 1 (Monday) might look like "fire at midnight on the 21st if it is also a Monday", but cron actually fires on every Monday and also at midnight on the 21st of every month, even when the 21st is not a Monday. To express "Monday the 21st only", you have to combine the rule with shell logic in the command rather than in the cron expression itself.
When one of the two day fields is the wildcard *, the restricted field controls matching on its own. 0 9 * * 1-5, for instance, fires at 09:00 on weekdays only, because day-of-week is restricted and day-of-month is unrestricted. A more subtle pattern is 0 9 15 * 1, which the parser would compute as the next five Mondays interleaved with the next five 15ths — a larger set than most people intend, and one the parser will gladly display so the mistake is obvious before deployment.
Common Cron Examples for Quick Reference
The cheat-sheet-style table below covers the schedules a developer reaches for most often. Each row uses only numeric values, the * wildcard, ranges, and steps; copy any of them directly into a crontab line and then verify with the parser.
| Schedule | Expression |
|---|---|
| Every minute | * * * * * |
| Every 15 minutes | */15 * * * * |
| Every day at midnight | 0 0 * * * |
| Weekdays at 09:00 | 0 9 * * 1-5 |
| First of the month at 03:30 | 30 3 1 * * |
| Sundays at 02:00 | 0 2 * * 0 |
| Hourly between 09:00 and 17:00, weekdays only | 0 9-17 * * 1-5 |
| Quarter past and quarter to, every hour | 0,15,30,45 * * * * |
For a more structured way to build an expression from a desired cadence without memorizing field order, the Cron Job Schedule guide walks through the same building blocks in reverse. Once you have an expression, paste it into the Cron Parser and confirm the next five runs match the schedule you intended.
Limits and Safety Bounds
A strict parser is also a safety net for malformed input. The next-run calculation scans forward by whole minutes and stops if five matches cannot be found within five years, which keeps a sparse expression like 0 0 29 2 * (midnight on February 29) from locking the browser tab while it waits for the next leap year. Calendar validity is handled by JavaScript's Date object, so day 31 naturally skips months without a 31st and February rules respect leap years without any extra code on your part.
Other inputs the parser rejects: a field count other than five, a sixth field intended as a command, names such as JAN or MON, nicknames such as @hourly or @reboot, seconds or year fields, Quartz question marks, last-day syntax, hashed schedules, and random ranges. Each of those features exists in some scheduler dialect, but supporting all of them would make the parser a different tool — one that no longer matches the classic Cronie grammar your crontab file expects. The parser deliberately does not execute commands, contact a server, or save expressions. Treat its output as a verification aid: confirm the production scheduler's time zone, daylight-saving policy, day-field semantics, and supported extensions before deploying a critical backup, billing, notification, or maintenance job.
For a deeper look, see Border Radius Generator Cheat Sheet: Values and Order.