What this tool does
This cron expression generator translates a schedule into a sentence and shows the next five times it will actually run. You type an expression, and it tells you what it means in plain English — which is the part that goes wrong, because an expression can be syntactically perfect and still schedule something entirely different from what you had in mind.
It also reports the specific error when the expression is invalid, rather than failing silently the way crontab does when you install a broken line.
How to use it
- Type or paste an expression into the field, or start from one of the common schedules.
- Read the sentence below it. If it does not match your intent, the expression is wrong, however correct it looks.
- Check the next five runs. Times are shown in your own timezone.
- Copy the expression into your crontab, CI configuration or scheduler.
The five fields
┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month (1–12 or JAN–DEC)
│ │ │ │ ┌───────────── day of week (0–7 or SUN–SAT, where 0 and 7 are Sunday)
│ │ │ │ │
* * * * *
Each field accepts a single value, a list (1,15), a range (9-17), a step (*/10), or a range
with a step (0-30/5). Month and day-of-week also accept three-letter names, which read better and
are harder to get wrong than remembering whether the week starts at zero.
Cron expression reference
Thirty schedules people actually install, with what each one reads as and when it fires. Every row was checked against the explainer above, so the wording here and the sentence the tool produces never disagree. Where a schedule has a page of its own, the reading links to it.
| Expression | Reads as | When it fires |
|---|---|---|
* * * * * | Every minute | 1,440 times a day, at :00 through :59 |
*/5 * * * * | Every 5 minutes | :00, :05, :10 and so on to :55 |
*/10 * * * * | Every 10 minutes | :00, :10, :20, :30, :40, :50 |
*/15 * * * * | Every 15 minutes | :00, :15, :30, :45 of every hour |
*/30 * * * * | Every 30 minutes | :00 and :30 of every hour |
0 * * * * | Every hour | On the hour, 24 times a day |
30 * * * * | Hourly, at half past | :30 of every hour |
0 */2 * * * | Every 2 hours | 00:00, 02:00, 04:00 and on to 22:00 |
0 */6 * * * | Every 6 hours | 00:00, 06:00, 12:00, 18:00 |
0 */5 * * * | Every 5 hours, unevenly | 00:00, 05:00, 10:00, 15:00, 20:00, then only 4 hours to midnight |
0 0 * * * | Every day at midnight | 00:00, every day of the year |
5 0 * * * | Daily, five past midnight | 00:05, off the midnight pile-up |
0 9 * * 1-5 | Every working morning | 09:00, Monday to Friday |
*/15 9-17 * * 1-5 | Quarter-hourly in office hours | :00, :15, :30, :45 from 09:00 to 17:45, weekdays |
0 22 * * 1-5 | Every working night | 22:00, Monday to Friday |
0 9 * * 1 | Every Monday at 09:00 | 09:00 on Mondays and no other day |
0 0 * * 0 | Every Sunday at midnight | 00:00 on Sundays; 7 names the same day |
0 0 * * 6,0 | Every weekend day | 00:00 on Saturday and Sunday |
0 0 1 * * | Every month on the 1st | 00:00 on the first day of each month |
0 0 1 */3 * | Every quarter | 00:00 on 1 January, 1 April, 1 July, 1 October |
0 0 28-31 * * | Every candidate last day | 00:00 on the 28th to the 31st, so the script decides |
0 0 1 1 * | Once a year | 00:00 on 1 January |
@hourly | Every hour | Expands to 0 * * * * |
@daily | Every day at midnight | Expands to 0 0 * * * |
@midnight | Every day at midnight | The same schedule as @daily, spelled differently |
@weekly | Every Sunday at midnight | Expands to 0 0 * * 0 |
@monthly | Every month on the 1st | Expands to 0 0 1 * * |
@yearly | Once a year | Expands to 0 0 1 1 * |
@annually | Once a year | The same schedule as @yearly |
@reboot | Not a schedule at all | Once, when the daemon starts. No clock is involved |
The shortcuts at the bottom are the ones crontab accepts in place of all five fields, and this tool
expands each of them before reading it. @reboot is the exception, and the reason it is listed here
rather than quietly omitted: it is an event, not a time, so there is no next run to compute and no
sentence to write. Paste it above and you get an error, which is the honest answer. If you need
something to happen at boot, a service unit with After=network.target is the tool for it, not a
line in the crontab.
The OR rule that catches everyone
The one behaviour worth memorising: when both day-of-month and day-of-week are restricted, cron
runs the job when either matches. 0 0 13 * 5 does not mean "Friday the 13th" — it means the
13th of every month, plus every Friday, which is roughly nine times more often.
To express "Friday the 13th" you need the check inside your script, not in the schedule. This is a quirk of the original Vixie cron, kept for compatibility ever since, and it is why the sentence this tool produces says "and on" rather than joining the two conditions.
Steps do not mean intervals
*/5 reads as "every 5 minutes" and behaves that way, but only because 5 divides 60. */7 fires at
minute 0, 7, 14, 21, 28, 35, 42, 49 and 56 — then the hour rolls over and it fires at 0 again, four
minutes later. If your job must run at a fixed interval that does not divide evenly into an hour,
cron is the wrong tool: use a timer that schedules the next run when the previous one finishes.
Before you install it
Two failures account for most cron incidents, and neither is about syntax. The first is timezone:
the schedule follows the machine, and a server on UTC will not respect your local working hours.
The second is environment — cron runs with a minimal PATH and none of your shell profile, so a
command that works in your terminal may not resolve at all. Use absolute paths, and redirect output
somewhere you will read it.
Where the expression runs matters
The same five fields behave slightly differently depending on who reads them. Linux crontab, GitHub
Actions and most CI systems use the format described here. Kubernetes CronJobs use it too, but
interpret the schedule in UTC unless the spec says otherwise. Java schedulers built on Quartz add a
seconds field at the front and support L, W and #, so an expression copied from a Quartz
example will either be rejected here or, worse, accepted with a different meaning.
When in doubt, check the documentation of the scheduler you are targeting before trusting an expression you found in an answer online.