Cron Expression Explainer
Paste a cron expression and read it back in plain English, column by column, with the next five run times in UTC, your own zone or the server's.
In words
Common schedules
Runs shown in
UTC, the zone your browser reports, or a server's zone chosen from the list — the runs are computed in it, not shifted afterwards.
Next five runs
How to use
- Clear the box and paste your own expression over the */5 * * * * that is sitting there.
- Read the sentence at the top and check that it matches what you meant, especially the day-of-week part, which is where most mistakes hide.
- Look at the next five run times at the foot, and choose the zone they are shown in: UTC, your browser's zone, or the server's zone from the list.
- Not sure where to start? Press one of the four common schedules and edit that instead. Each column's card names its field, so you never lose track of which is which.
Reading a cron expression
A cron expression is five numbers and some punctuation, and the gap between the right one and the wrong one is usually a single character. Paste yours into the box and it comes back as a sentence. Feed it 0 9 * * 1-5 and you get At 09:00, Monday through Friday, the clock written 24-hour so it agrees with the runs. Under the sentence each column gets a card saying what it means, and the next five run times sit at the foot, down to the second, in UTC, your own zone or a server's. The box arrives with */5 * * * * already in it, so there is a worked answer on screen before you touch anything.
Five fields, left to right: minute 0 to 59, hour 0 to 23, day of month 1 to 31, month 1 to 12, and day of week 0 to 7 with Sunday sitting at both ends. Each one takes a single number, a list like 1,15, a range like 1-5, a step like */5, or an asterisk for every value. Month and day names work too, so 0 9 * JAN-MAR MON-FRI parses. A leading seconds field is accepted if your scheduler wants six.
The lowercase macros are handled: @hourly, @daily, @weekly, @monthly, @yearly and @annually all resolve and get explained. Capitals are refused at the field with the lower-case form to use, so @DAILY says @daily. @reboot is refused as well, since booting is not a clock time and there is no next run to compute from it. Four common schedules sit just above the box, the one matching what is in it pressed, and pressing one drops that expression into the box so you can edit from there instead of from a blank field.
Good to know
- Schedulers disagree about the night the clocks change. cronie never runs a time that does not exist and runs a repeated one twice; Debian's Vixie cron runs a skipped job soon after the change and a repeated one once; the runs here follow cron-parser, which moves a skipped time to the next hour and runs a repeated one once. Check your own scheduler before relying on a run inside the changed hour.
- Quartz syntax is partly supported, because the underlying parser is standard cron with a few extras. The ? placeholder works, L in the day-of-month field gives you the last day of the month, and 1#2 gives you the second Monday. The W modifier does not: 0 0 15W * * is refused at the field, as are LW, L-3 and a trailing year field.
Frequently asked questions
Which field is which, left to right?
Minute, hour, day of month, month, day of week. The ranges are 0-59, 0-23, 1-31, 1-12 and 0-7. An asterisk means every value, a slash sets a step so */5 is every fifth, a hyphen sets a range, and commas list values one by one. Each column's card on the page names its field and says what the token in it means.
What is the cron expression for every 5 minutes?
*/5 * * * *, which is what the box is prefilled with. The */5 in the minute field means every fifth minute; the four asterisks after it mean every hour, every day of the month, every month and every day of the week. Same idea for other intervals: */10 * * * * for ten minutes, */30 * * * * for half an hour, and 0 * * * * for the top of every hour.
How do I write a daily, weekly or monthly schedule?
Daily at midnight is 0 0 * * *. Every Sunday at midnight is 0 0 * * 0. The first of the month is 0 0 1 * *. Weekday mornings at nine is 0 9 * * 1-5. To move the time, change the first two fields and leave the rest alone, so 30 8 * * * fires at 08:30 every day. Paste any of them in and the run times confirm it.
Do the @daily and @hourly shortcuts work here?
They do, as long as you type them in lowercase. @hourly, @daily, @weekly, @monthly, @yearly and @annually are all recognised and explained, and @daily is exactly 0 0 * * *. @DAILY in capitals is refused with the lower-case form to use. So is @reboot, which is deliberate: it means run once when the machine starts, and a boot has no place on a calendar.
My job runs at a different time than the preview says. What went wrong?
Almost certainly the timezone. Your scheduler uses whatever timezone the server is set to, so choose Server zone and pick it from the list: the runs are then worked out in that zone, with UTC beneath each one. A 30 2 * * * backup on a box set to Europe/Berlin goes off at 02:30 Berlin time, which is 01:30 UTC in winter and 00:30 in summer, and the page names the night the clocks change. Run date on the server, or look for a TZ or CRON_TZ line in the crontab, if you are not sure which zone it is.
Is Sunday 0 or 7 in the day-of-week field?
Both. Standard cron accepts 0 and 7 for Sunday, which is why the range is written 0-7 rather than 0-6. Paste 0 0 * * 0 and then 0 0 * * 7 and you will get the same sentence back from both. Day names work as well, so MON, TUE and MON-FRI all parse the way you would hope.
Can I paste a six-field cron with seconds?
Yes, a leading seconds field is accepted. Spring, Quartz and a few job runners write six fields, so 0 30 9 * * * reads as 09:30 every day rather than as a broken five-field expression. The four common schedules stick to the five-field form, since that is what crontab itself uses.
Do Quartz expressions with ?, L and # work?
Some of them. The ? placeholder is accepted wherever Quartz allows it, L on its own in the day-of-month field means the last day of the month, and 1#2 in the day-of-week field means the second Monday. What is not supported is W, the nearest-weekday modifier, so 0 0 15W * * fails. LW, L-3 and a seventh year field fail as well. If your scheduler is really Quartz, treat this as a sanity check on the common cases rather than as a Quartz validator.
What happens to 0 0 29 2 * in a year that is not a leap year?
It waits. Paste it in and the run times skip straight to the next 29 February, which from 2026 means 2028 and then 2032. Cron does not round February 29 down to the 28th, so a job scheduled that way runs once every four years. A February 31 like 0 0 31 2 * is refused at the field, which says day of month 31 never comes in February, rather than silently never firing.
Missing something in Cron Expression Explainer? Suggest a feature →
Tell someone who needs this.