What the result contains
What This Tool Provides
Build and read five-field cron expressions. Type a schedule and get it back in plain English along with the next five times it would actually fire, or start from a preset and adjust. The tool also warns about the one rule almost everyone misreads: when both day fields are restricted, cron combines them with OR rather than AND.
- A plain-English reading of any five-field expression
- The next five run times in your own timezone
- A specific warning when the day-of-month and day-of-week OR rule applies
- Field-level error messages naming which field is wrong and why
How to Use This Tool
- Start from a preset or type oneThe buttons cover the common schedules; the field accepts any five-field expression, including the @daily style aliases.
- Read the descriptionThe plain-English line says what the expression actually means, which is usually where a mistake becomes obvious.
- Check the next five runsReal dates and times are the fastest sanity check. An expression that looks right and fires on the wrong day shows it here.
How It Works
Each of the five fields is expanded into the explicit set of values it matches. A wildcard becomes the field’s whole range, a range fills in between its endpoints, a step walks the range at that interval, and a list unions the parts — with month and day-of-week also accepting their three-letter names. Day-of-week is then normalized so that 7 and 0 both mean Sunday, which is why a range like 5-7 covers Friday through Sunday rather than overflowing. Finding the next run is a minute-by-minute walk forward from now, testing each candidate against the five sets; this is not the fastest possible algorithm, but it is obviously correct, and it terminates rather than looping forever on an expression such as 30 February that can never match.
Worked Examples
Weekdays at nine
- Input
0 9 * * 1-5- Output
At 09:00 on Monday, Tuesday, Wednesday, Thursday and Friday.
The day-of-week range covers Monday to Friday. Only one day field is restricted, so ordinary AND semantics apply.
The OR rule catching someone out
- Input
0 0 1 * MON- Output
At 00:00 on day 1 of the month, and also on Monday.
This does not mean "the 1st, but only when it is a Monday". Because both day fields are restricted, cron fires on the 1st AND on every Monday — roughly five times a month rather than once or twice a year.
A step over a range
- Input
0 9-17/4 * * *- Output
At 09:00, 13:00 and 17:00.
The step applies within the range rather than across the whole field, giving three runs during office hours.
The Day-of-Month and Day-of-Week OR Rule
Every pair of cron fields is combined with AND — a job runs when the minute matches AND the hour matches AND the month matches. Every pair except one. When both the day-of-month and the day-of-week fields are restricted, cron switches to OR: the job runs on a day matching either.
The consequence is that 0 0 1 * MON does not mean "midnight on the first of the month, if that day is a Monday". It means "midnight on the first of the month, and also midnight every Monday" — around five runs a month instead of the one or two a year the author intended. This behavior is documented in the crontab manual, it is consistent across Vixie cron and its descendants, and it still catches people who have written cron schedules for years.
The rule only applies when *both* fields are restricted. If either is a wildcard, the other simply decides, which is why the vast majority of expressions behave the way people expect and the trap stays hidden until the day someone writes a schedule using both. This tool detects the condition and says so explicitly rather than leaving you to notice from the run times — though the run times will show it too.
| Expression | Day of month | Day of week | When it fires |
|---|---|---|---|
| 0 0 * * MON | Wildcard | Restricted | Every Monday — weekday decides |
| 0 0 1 * * | Restricted | Wildcard | The 1st — day of month decides |
| 0 0 1 * MON | Restricted | Restricted | The 1st, and also every Monday (OR) |
| 0 0 * * * | Wildcard | Wildcard | Every day |
Which Cron Is This, Exactly
Cron is not one format. This tool reads the standard five-field crontab expression — minute, hour, day-of-month, month, day-of-week — which is what Vixie cron uses and what most CI schedulers, container orchestrators and cloud triggers accept.
Quartz, the scheduler underneath much of the Java ecosystem including Spring, uses six or seven fields: it adds seconds at the front and an optional year at the end, and its day-of-week field is 1-7 with Sunday as 1 rather than 0-6 with Sunday as 0. Pasting a Quartz expression here gets you an explanation rather than a wrong answer, because a six-field expression parsed as five fields would produce a confidently incorrect schedule. Quartz also supports ? , L , W and # , none of which exist in standard cron.
Non-standard extensions vary elsewhere too. The @daily and @hourly aliases are widely supported and expanded here. @reboot is common but has no schedule to compute, since it depends on when the machine starts. Some implementations accept step syntax in places others reject. When precision matters, the authority is the manual for the specific cron your job will run under.
Timezones, and the Hour That Happens Twice
The run times here are computed in your browser’s timezone, because that is the only one the page can know. Your server is very probably not in it. Most production schedulers run in UTC, so a job you reason about as 09:00 fires at a different local time — and, if your region observes daylight saving, at a different local time in summer than in winter.
The daylight-saving transitions are where scheduled jobs genuinely break. When clocks go forward, the skipped hour does not happen, so a job scheduled at 02:30 simply does not run that day. When clocks go back, that hour occurs twice, and depending on the implementation the job may run twice — which matters a great deal if it charges cards, sends email, or moves money.
The practical defences are unglamorous. Schedule anything sensitive outside the 01:00 to 03:00 window where transitions happen. Run your schedulers in UTC so the problem cannot arise. And make the job itself idempotent, so that running twice is harmless — which is better engineering than trying to guarantee it never will.
Before You Ship a Schedule
The single most useful habit is the one this page is built around: read the next few run times rather than trusting the expression. Almost every cron mistake is visible immediately in a list of real dates, and almost none is visible from staring at five fields of numbers. An expression firing every minute instead of every hour, or on the wrong weekday, or five times a month because of the OR rule, all announce themselves at a glance.
Two smaller checks are worth the seconds. A job that logs epoch timestamps is easier to verify against a schedule once you convert those timestamps to readable dates — a run that fired an hour off is usually a timezone problem rather than a cron one. And when a schedule lives inside a YAML pipeline definition, converting that YAML to JSON makes it obvious whether the cron string is attached to the job you think it is, since indentation mistakes hide well in YAML and not at all in JSON.
Scheduled jobs also carry credentials, and they are among the longest-lived secrets in most systems: a token minted for a nightly job tends to outlast everyone who remembers creating it. Generate a fresh one rather than reusing a shared key, and note that a Kubernetes CronJob mounting a secret stores it Base64-encoded rather than encrypted — decoding it shows what the job actually receives. Where the scheduler is configured through an API rather than a crontab, validating that JSON body catches a malformed schedule before the job silently never runs.
Finally, if you are auditing a repository full of scheduled jobs, a pattern search across the config finds every cron string faster than reading each file — and the expressions that turn out to be duplicated, or to fire far more often than anyone remembers, are usually the interesting ones.
Important Edge Cases
- Day-of-week accepts both 0 and 7 for Sunday, so a range such as 5-7 covers Friday, Saturday and Sunday rather than being out of range.
- A bare value with a step, such as 5/20 in the minute field, means "from 5 to the end of the field in steps of 20" rather than a single value.
- An expression that can never match, such as 30 February, produces no run times rather than searching forever.
- The @daily, @hourly and @weekly aliases are expanded to their five-field equivalents. @reboot has no schedule and is not supported.
- A six or seven field expression is rejected with an explanation rather than being misread as a five-field one.
Limitations
- Only the standard five-field format is read. Quartz and Spring expressions, and their ? , L , W and # syntax, are not supported.
- Run times are computed in your browser’s timezone; a server running in UTC will fire at different local times.
- Daylight-saving transitions are not modelled, so a run near a clock change may differ from what your scheduler actually does.
- The tool cannot know whether your scheduler is running, whether a previous run overlapped, or how your platform handles a missed run.
- Next-run search stops after five years, which only matters for extremely rare schedules.
Input handling
Private Browser Processing
Expressions are parsed and run times computed entirely in your browser. Nothing is uploaded, stored, or logged, and the only clock consulted is your own device’s.
Google Analytics records page visits and whether a tool finished or failed, but these tool implementations do not send field values, generated passwords, QR payloads, uploaded QR images, or camera frames to analytics or a Tiny Tiny Tools processing endpoint.
See the Privacy Policy for site-wide details.
Questions About This Tool
Why does my expression run more often than I expect?
Most often the day-field OR rule. When both day-of-month and day-of-week are restricted, cron fires on either, not both — so 0 0 1 * MON runs on the 1st and on every Monday. The tool warns whenever an expression depends on this.
Is Sunday 0 or 7?
Both. Standard cron accepts either, which is why a range such as 5-7 is valid and covers Friday to Sunday. Quartz is different again, numbering the week 1-7 with Sunday as 1.
Why is my six-field expression rejected?
Because it is a different dialect. Quartz and Spring add a seconds field at the front and an optional year at the end. Parsing it as five fields would produce a confident, wrong answer, so the tool explains instead.
What timezone are the run times in?
Your browser’s, since that is the only one this page can know. Most servers run in UTC, so check what your scheduler uses before trusting the local times shown here.
What happens at a daylight-saving change?
A job scheduled in the skipped hour does not run that day; a job in the repeated hour may run twice, depending on the implementation. Schedule sensitive jobs outside 01:00 to 03:00, or run the scheduler in UTC.
Does it support @reboot?
No. The @daily, @hourly, @weekly, @monthly and @yearly aliases are expanded to their five-field equivalents, but @reboot has no schedule to compute — it depends entirely on when the machine starts.