Skip to the tool
DevToolBench

Cron Expression Generator

Explain a cron schedule and preview its next runs.

minute hour day-of-month month day-of-week

At every 15th minute past every hour from 9 through 17 on every day-of-week from Monday through Friday.

Fields

minute
*/15
hour
9-17
day of month
*
month
*
day of week
1-5

Next 5 runs

Times shown in your own timezone.

Common schedules

Everything runs in your browser. Nothing you type is sent to a server.

Found a bug in this tool? Report it.

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

  1. Type or paste an expression into the field, or start from one of the common schedules.
  2. Read the sentence below it. If it does not match your intent, the expression is wrong, however correct it looks.
  3. Check the next five runs. Times are shown in your own timezone.
  4. 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.

ExpressionReads asWhen it fires
* * * * *Every minute1,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 hourOn the hour, 24 times a day
30 * * * *Hourly, at half past:30 of every hour
0 */2 * * *Every 2 hours00:00, 02:00, 04:00 and on to 22:00
0 */6 * * *Every 6 hours00:00, 06:00, 12:00, 18:00
0 */5 * * *Every 5 hours, unevenly00:00, 05:00, 10:00, 15:00, 20:00, then only 4 hours to midnight
0 0 * * *Every day at midnight00:00, every day of the year
5 0 * * *Daily, five past midnight00:05, off the midnight pile-up
0 9 * * 1-5Every working morning09:00, Monday to Friday
*/15 9-17 * * 1-5Quarter-hourly in office hours:00, :15, :30, :45 from 09:00 to 17:45, weekdays
0 22 * * 1-5Every working night22:00, Monday to Friday
0 9 * * 1Every Monday at 09:0009:00 on Mondays and no other day
0 0 * * 0Every Sunday at midnight00:00 on Sundays; 7 names the same day
0 0 * * 6,0Every weekend day00:00 on Saturday and Sunday
0 0 1 * *Every month on the 1st00:00 on the first day of each month
0 0 1 */3 *Every quarter00:00 on 1 January, 1 April, 1 July, 1 October
0 0 28-31 * *Every candidate last day00:00 on the 28th to the 31st, so the script decides
0 0 1 1 *Once a year00:00 on 1 January
@hourlyEvery hourExpands to 0 * * * *
@dailyEvery day at midnightExpands to 0 0 * * *
@midnightEvery day at midnightThe same schedule as @daily, spelled differently
@weeklyEvery Sunday at midnightExpands to 0 0 * * 0
@monthlyEvery month on the 1stExpands to 0 0 1 * *
@yearlyOnce a yearExpands to 0 0 1 1 *
@annuallyOnce a yearThe same schedule as @yearly
@rebootNot a schedule at allOnce, 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.

Frequently asked questions

What do the five fields mean?

In order — minute, hour, day of month, month, day of week. A star means "every", so `30 2 * * *` reads as "at minute 30 of hour 2, every day of every month, every weekday" — that is, daily at 02:30.

Why does my job run on days I did not expect?

When both day-of-month and day-of-week are restricted, cron treats them as OR, not AND. `0 0 13 * 5` runs on the 13th of the month *and* on every Friday, which is far more often than most people intend. Leave one of the two as a star unless you genuinely want both.

Which timezone does cron use?

The timezone of the machine running it, not yours. A container defaulting to UTC will fire your "09:00" job at 09:00 UTC, and daylight saving means the local hour shifts twice a year. Set the timezone explicitly, or schedule in UTC and convert when you read the logs.

Can I use the L, W and # characters here?

No, and neither can crontab. Those belong to the Quartz dialect used by Java schedulers, along with a sixth field for seconds. This tool reads the five-field crontab format that Linux, cron and most CI systems use.

What does */5 actually mean?

Every 5th value counting from the start of the field, not "every 5 minutes from now". `*/5` in the minute field fires at 0, 5, 10 and so on, so the interval resets at the top of each hour — `*/7` fires at 0, 7, 14, 21, 28, 35, 42, 49, 56 and then again at 0, only 4 minutes later.

Related tools

Updated