Cron Expression Generator
Paste a cron expression to see what it means in plain English, the next 10 times it will run in your timezone, and — if it is not running — what is wrong with it. Supports standard cron, Quartz, Spring and AWS EventBridge, and runs entirely in your browser.
Build it field by field
Use * for every value, 5 for one value, 1-5 for a range, */15 for a step, or 1,3,5 for a list. The builder covers standard 5-field cron; edit the box above directly for Quartz or EventBridge.
Why isn't my cron job running?
Next 10 runs
Field by field
| Field | Value | Allowed | Means |
|---|
Runs in your browser. Nothing uploaded.
How to use it
- Pick your dialect. Standard cron for Linux crontab, Quartz for Java and Spring, AWS EventBridge for scheduled rules. The field count changes with it, so get this right first.
- Paste an expression, pick a preset, or build it field by field. The preset buttons cover the ten schedules most people want. If you would rather not write cron at all, open “Build it field by field” and fill in the five boxes. The description and the run list update as you type.
- Check the timezone. We detect yours and show it above the run list. Change it to match your server if they differ, because that’s where the job actually runs.
- Read the next ten runs. If something’s wrong with the schedule, a panel appears above them telling you what. The field-by-field table underneath shows exactly which values each field resolved to.
Copy the expression when you’re happy with it, or copy a link to the whole thing — the expression, dialect and timezone travel in the URL, so you can paste it into a ticket and the other person sees exactly what you saw.
What a cron expression is
A cron expression is a short string that describes a repeating schedule. It’s been the standard way to say “run this at this time” on Unix systems since the 1970s, and it spread from there into schedulers, CI systems and cloud platforms.
Standard cron uses five fields separated by spaces:
┌─────── minute (0-59)
│ ┌───── hour (0-23)
│ │ ┌─── day of month (1-31)
│ │ │ ┌─ month (1-12)
│ │ │ │ ┌ day of week (0-6, Sunday is 0)
│ │ │ │ │
0 9 * * 1-5
That example reads: at minute 0, of hour 9, on any day of the month, in any month, on days 1 through 5 of the week. In plain English, 9am on weekdays.
An asterisk means “every value”. A number means that value. Beyond that you get ranges with a hyphen, lists with commas, and steps with a slash. That’s most of the syntax.
The part that catches people out isn’t the syntax. It’s that a valid expression can still be the wrong schedule, and cron gives you no feedback at all — it just quietly runs at times you didn’t intend, or never runs. That’s the gap this page is built to close.
Which dialect do you need?
Cron isn’t one standard. There are several, they look nearly identical, and an expression written for one will often be silently wrong in another.
| Dialect | Fields | Seconds | Day-of-week numbering | Key rule |
|---|---|---|---|---|
| Standard cron (crontab) | 5 | No | 0-6, Sunday is 0 (7 also works) | Day-of-month and day-of-week are OR’d when both are set |
| Quartz / Spring | 6, or 7 with a year | Yes, first field | 1-7, Sunday is 1 | ? required in exactly one of the two day fields |
| AWS EventBridge | 6, year last | No | 1-7, Sunday is 1 | * not allowed in both day fields at once |
Two differences do most of the damage.
The first is the seconds field. Quartz puts seconds first, so a six-field Quartz expression has everything shifted one place right compared to standard cron. Paste 0 0 12 * * ? into a Linux crontab and it won’t mean noon — it won’t parse at all.
The second is day-of-week numbering. Standard cron counts Sunday as 0. Quartz and EventBridge count Sunday as 1. So * * * * 1 means Monday in crontab and Sunday in Quartz. Nothing errors. The job just runs on the wrong day, every week, until someone notices.
Using cron with AWS EventBridge
EventBridge has its own rules, and they’re the ones people hit hardest because the AWS console rejects the expression without always explaining why.
EventBridge uses six fields: minute, hour, day-of-month, month, day-of-week, year. There’s no seconds field, which surprises people coming from Quartz, and the year field is mandatory — you’ll usually want * there.
The rule that trips everyone up: you cannot use * in both the day-of-month and day-of-week fields at the same time. One of them has to be ?. AWS does this deliberately to avoid the OR-versus-AND ambiguity that standard cron has, but the error message is unhelpful if you don’t already know the rule.
So a daily 9am job on EventBridge is:
0 9 * * ? *
Not 0 9 * * * *, which AWS rejects. And weekdays at 9am is:
0 9 ? * MON-FRI *
Note the ? moved to the day-of-month field, because day-of-week is now the one doing the work. Exactly one of the pair is always ?.
One more thing worth knowing: EventBridge schedules run in UTC unless you’re using EventBridge Scheduler with an explicit timezone. Set the timezone selector above to UTC when you’re checking an EventBridge rule, or the times you see won’t be the times AWS fires at.
How the syntax works
Each field takes the same four constructs.
| Symbol | Means | Example | Result |
|---|---|---|---|
* |
Every value | * * * * * |
Every minute |
, |
A list | 0,30 * * * * |
On the hour and half past |
- |
A range | 0 9-17 * * * |
Hourly from 9am to 5pm |
/ |
A step | */15 * * * * |
Every 15 minutes |
? |
No specific value (Quartz, AWS only) | 0 9 * * ? * |
Daily at 9am on EventBridge |
Ranges and steps combine. 0 9-17/2 * * * means every second hour between 9 and 5 — so 9, 11, 13, 15 and 17.
The field ranges are:
| Field | Range | Names accepted |
|---|---|---|
| Seconds (6-field only) | 0-59 | — |
| Minute | 0-59 | — |
| Hour | 0-23 | — |
| Day of month | 1-31 | — |
| Month | 1-12 | JAN-DEC |
| Day of week | 0-6 or 1-7, depending on dialect | SUN-SAT |
| Year (Quartz optional, AWS required) | 1970-2199 | — |
Names are usually easier to read and harder to get wrong. 0 9 * * MON-FRI says what it does. 0 9 * * 1-5 makes you remember which day is 1.
Standard cron also has shortcuts: @daily, @hourly, @weekly, @monthly, @yearly and @reboot. They’re convenient but they’re not portable — Quartz and EventBridge don’t accept them. @reboot is different from the rest: it isn’t a time at all, it runs once when the machine starts, which is why this tool shows no fire times for it.
Worked examples
Every weekday at 9am. 0 9 * * 1-5 — minute 0, hour 9, any day of month, any month, Monday through Friday. The most common schedule there is.
Every 15 minutes. */15 * * * * — fires at :00, :15, :30 and :45 past every hour. A common mistake here is writing 0/15, which works in Quartz but isn’t valid in standard cron.
First day of every quarter. 0 0 1 1,4,7,10 * — midnight on the 1st of January, April, July and October.
Every six hours. 0 */6 * * * — midnight, 6am, noon and 6pm. Note the step is in the hour field. Putting it in the minute field gives you something very different.
Noon on the last Friday of the month. You can’t do this in standard cron. There’s no “last” operator, so the usual workaround is to run daily and check the date inside the job. Quartz has L for exactly this: 0 0 12 ? * 6L.
A schedule that never runs. 0 0 31 2 * is valid syntax. February has never had a 31st and never will. Cron accepts it and simply never fires. Paste it above and the diagnostic says so instead of showing you an empty list.
Common schedules, ready to use
Most cron expressions people need are one of about ten. The preset buttons load these straight into the box, and the next run times update immediately so you can check the one you picked is the one you meant.
| What you want | Expression | Runs |
|---|---|---|
| Every minute | * * * * * |
1,440 times a day |
| Every 5 minutes | */5 * * * * |
288 times a day |
| Every 15 minutes | */15 * * * * |
96 times a day |
| Every 30 minutes | */30 * * * * |
48 times a day |
| Every hour, on the hour | 0 * * * * |
24 times a day |
| Every 2 hours | 0 */2 * * * |
12 times a day |
| Every day at midnight | 0 0 * * * |
Once a day |
| Every weekday at 9am | 0 9 * * 1-5 |
5 times a week |
| Every week (Sunday midnight) | 0 0 * * 0 |
Once a week |
| Every month (1st, midnight) | 0 0 1 * * |
12 times a year |
A note on */5. The step operator counts from the start of the range, not from now. So */5 in the minute field fires at :00, :05, :10 and so on — not five minutes after you install it. And */7 does not divide evenly into 60, so it fires at :00, :07 … :56 and then again at :00 four minutes later. Steps that do not divide their range cleanly are a common source of surprise.
There is no “every 30 seconds” in standard cron, because the smallest unit is a minute. You need Quartz, which has a seconds field, or two jobs where one sleeps 30 seconds first.
Cron on other platforms
The five-field syntax is close to universal, but where you put it and what it accepts varies.
| Platform | Dialect | Worth knowing |
|---|---|---|
| Linux crontab | Standard 5-field | Runs in the server’s timezone, not yours. crontab -e to edit, crontab -l to list. |
| GitHub Actions | Standard 5-field | Always UTC, no exceptions. Scheduled runs are also queued and can be delayed under load. |
| Kubernetes CronJob | Standard 5-field | Has a timeZone field in recent versions. Missed runs are governed by startingDeadlineSeconds. |
| Jenkins | Standard 5-field, extended | Adds H, which spreads load by hashing the job name to a value. H * * * * means “once an hour, at a consistent but arbitrary minute”. |
| Spring / Quartz | Quartz 6-field | Leading seconds field. Needs ? in exactly one day field. |
| AWS EventBridge | EventBridge 6-field | Trailing year field, always UTC, and * is prohibited in both day fields at once. |
| Laravel | Standard 5-field | Written in PHP rather than cron text, but one real system cron entry runs the scheduler every minute. |
| Docker | Standard 5-field | Containers often ship without a cron daemon running at all. That is the usual reason a “correct” schedule never fires. |
Jenkins’ H deserves a mention because it is genuinely useful and unique. If a hundred jobs are all set to 0 * * * *, a hundred jobs start at once every hour. H * * * * gives each job its own minute, deterministically, so the load spreads without anyone choosing minutes by hand.
Common cron mistakes
- Assuming the server is in your timezone. It usually is not. This is the single most common cause of “it ran at the wrong time”.
- Expecting day-of-month AND day-of-week to combine. They do not. Standard cron treats them as OR, which is covered in detail below.
- Using
*/7and expecting even spacing. Steps restart at the beginning of each range. - Counting months from zero. Months are 1-12. Day-of-week is the field that starts at zero.
- Forgetting that cron has almost no environment. No
PATHto speak of, no shell profile. A script that runs fine in your terminal frequently fails under cron for this reason alone. Use absolute paths. - Not capturing output. If a job produces no logs, you cannot tell a job that failed from one that never ran. Redirect both streams to a file.
Why isn’t my cron job running?
Four causes account for nearly all of it.
The schedule can’t happen. Day 30 or 31 of February. Day 31 of a 30-day month. These parse fine and never fire. The tool checks eight years ahead before telling you a schedule never runs, so a leap-day job like 0 0 29 2 * is correctly reported as real but infrequent rather than broken.
Day-of-month and day-of-week are OR’d, not AND’d. This is the big one. In standard cron, when both those fields are restricted, the job runs on days matching either condition. So 0 0 13 * 5 is not “Friday the 13th” — it runs on every 13th of the month and on every Friday. That’s roughly nine times a month instead of once or twice a year. Quartz and EventBridge dodge this entirely by making you put ? in one of the fields.
Daylight saving. Twice a year, wall-clock time does something unusual. When clocks jump forward, an hour disappears — a job scheduled at 02:30 in a timezone that springs from 02:00 to 03:00 has no 02:30 to run at. Vixie cron, the default on most Linux systems, runs it at 03:00 when the clock jumps. Other schedulers skip it. When clocks go back, an hour repeats, and a job scheduled inside it can run twice. This tool flags both, calculated against the timezone you’ve selected rather than assumed.
Wrong dialect. Six fields pasted into a five-field crontab. Sunday numbered from the wrong end. ? used where it isn’t supported. Switch the dialect selector and see whether the expression suddenly makes sense.
If none of those apply, the problem probably isn’t the expression. Check that the cron daemon is running, that the crontab file ends with a newline, that the job’s PATH is what you expect — cron runs with a minimal environment — and that the script is executable.
Testing a schedule before you trust it
Reading the next ten runs above catches most mistakes, but a couple of things are worth checking on the machine itself.
Confirm what’s actually installed. crontab -l shows the current user’s jobs. A job you edited but never saved, or saved as the wrong user, is a common and confusing failure — root’s crontab and your own are different files.
Capture the output. Cron mails output by default, and on most servers that mail goes nowhere. Redirect it somewhere you’ll see: append >> /var/log/myjob.log 2>&1 to the command. Without 2>&1 you get standard output but lose the errors, which are the part you need.
Remember the environment is minimal. Cron doesn’t load your shell profile, so PATH is short and your aliases don’t exist. Use absolute paths to binaries, or set PATH explicitly at the top of the crontab.
Escape percent signs. In a crontab, % is special — it’s turned into a newline. A date format like date +%Y-%m-%d will break unless you write it as date +%Y-%m-%d. This one is genuinely obscure and costs people an afternoon.
Related tools
Getting the timezone wrong is the most expensive cron mistake, and it is the same mistake people make scheduling meetings — the time zone converter shows what a given time is elsewhere and warns you when a daylight saving change is near. If you are posting a schedule to a team on Discord, the Discord timestamp generator writes the time so every reader sees it in their own timezone. For job payloads and logs, the hex, binary and ASCII converter decodes byte output, and for secrets and tokens in a job’s environment see the JWT decoder and URL encoder.
Frequently asked questions
What is a cron expression?
A cron expression is a short string that describes a repeating schedule. Standard cron uses five fields — minute, hour, day of month, month, day of week — so "0 9 * * 1-5" means 9am on weekdays. Quartz and AWS EventBridge use six fields and add their own rules.
What is the difference between 5-field and 6-field (Quartz) cron?
Standard Unix cron has five fields and no seconds. Quartz adds a leading seconds field, making six, plus an optional trailing year. Quartz also requires a "?" in exactly one of the day-of-month and day-of-week fields, and its day-of-week is numbered 1-7 with 1 meaning Sunday, where standard cron uses 0-6.
What cron format does AWS EventBridge use?
EventBridge uses six fields — minute, hour, day of month, month, day of week, year — with no seconds field. It will not accept "*" in both the day-of-month and day-of-week fields at the same time; one of them must be "?". Its day-of-week is 1-7 with 1 meaning Sunday.
Why is my cron job not running?
The usual causes are a schedule that can never occur (such as 30 February), a day-of-month and day-of-week combination that behaves differently from what you expected, a daylight-saving boundary, or an expression written for the wrong dialect. Paste your expression above and the diagnostic will name which of these applies.
Why does my job run more often than I expected?
When both the day-of-month and day-of-week fields are restricted, standard cron treats them as OR, not AND. "0 0 13 * 5" does not mean "Friday the 13th" — it runs on every 13th of the month AND on every Friday. Quartz and EventBridge avoid this by requiring "?" in one of the two fields.
What timezone does cron use?
Standard cron uses the server's local timezone, which is often UTC but frequently is not. That is why this tool shows the timezone it is calculating in and lets you change it — a schedule that looks right in your local time may fire at a completely different moment on the server.
What happens to cron jobs during daylight saving?
Two things can go wrong. When clocks jump forward, a scheduled time inside the skipped hour does not exist; Vixie cron, the default on most Linux systems, runs the job at the moment the clock jumps instead. When clocks go back, an hour repeats, so a job scheduled in it can run twice. This tool flags both cases.
Does this send my expression to a server?
No. Parsing, the plain-English description and every fire time are calculated in your browser using JavaScript. Nothing is uploaded, and the page keeps working if you disconnect from the internet after it loads.
Guides that use this tool
Last updated: August 17, 2026