Search

Jump to a tool or a page

Cron expressions,
in plain English

Paste a crontab line to read what it actually means and see the next times it will fire in your time zone. Free, no sign-up required.

Cron expression

0

minute

0-59

9

hour

0-23

*

day of month

1-31

*

month

1-12

1-5

day of week

0-6

At 09:00 on Monday, Tuesday, Wednesday, Thursday and Friday.

Features

Everything you need to read a schedule with confidence.

Plain-English description

Every expression is translated into a sentence, so you can confirm a schedule means what you intended before deploying it.

Next runs previewed

The upcoming fire times are listed in your own time zone, which catches mistakes that a description alone can hide.

Field-level errors

An invalid value says which field is wrong and what range it accepts, rather than rejecting the whole line.

Runs in your browser

Parsing and scheduling happen locally. Nothing about your infrastructure is transmitted.

How to read a cron expression

Three steps, and everything updates as you type.

1

Paste the expression

Five fields, or a shorthand macro such as @daily. Each field is shown separately below the input with its valid range.

2

Read the description

The sentence describes exactly when the schedule fires, including a warning when the day fields interact in the surprising way.

3

Check the next runs

Six upcoming times, in your local zone. If they are not what you expected, the expression is not what you meant.

When you need this

Where a second opinion on a schedule is worth having.

Reviewing an inherited crontab

A line like "0 3 * * 0" is quick to misread. Seeing the next run times removes the guesswork before you change anything.

Writing a new scheduled job

Confirm a backup or report fires when you think it does, rather than waiting a day to discover it did not.

Debugging a job that fires too often

A stray step or a comma in the wrong field turns a daily task into an hourly one. The description makes it obvious.

Checking a CI or Kubernetes schedule

Pipeline schedules and CronJob specs use the same syntax, and both usually run in UTC rather than your local zone.

Understanding cron schedules

How the five fields combine, the day-of-month rule that fires jobs far more often than people expect, and the operational problems that follow: daylight saving, overlapping runs, and everything starting at midnight.

Reading the five fields

Each field accepts more than a single number. A comma separates a list, a hyphen gives a range, and a slash sets a step within whatever came before it.

  • Steps apply to a range*/15 in the minute field means 0, 15, 30, 45. It is a step through the whole range, not "every 15 minutes from now".
  • Names are allowedThe month and day-of-week fields accept three-letter names, so MON-FRI and JAN are valid and considerably more readable.
  • Sunday is both 0 and 7Every common implementation accepts either, which exists to accommodate the two conventions for numbering weeks.
*        every value
5        exactly 5
1,15     1 and 15
9-17     9 through 17
*/15     every 15th value, starting at the minimum
9-17/2   every 2nd value from 9 to 17

The day-of-month and day-of-week trap

This is the one genuine surprise in cron syntax, and it catches experienced people. Every other pair of fields is combined with AND: an expression fires only when the minute matches and the hour matches and the month matches.

The two day fields are different. When both are restricted, they are combined with OR. The job fires when either the day of month matches or the day of week matches.

The behaviour is inherited from the original Unix implementation and is now specified by POSIX, so it is consistent across implementations rather than a bug in any of them.

0 0 1 * *     midnight on the 1st
0 0 * * 1     midnight every Monday
0 0 1 * 1     midnight on the 1st AND every Monday
              (roughly 16 times a month, not once)

If you need "the first Monday of the month", cron alone cannot express it. The usual approach is to schedule for every Monday and exit early inside the job unless the date is in the first seven days.

Time zones and daylight saving

A cron expression names a wall-clock time, and wall-clock time is not continuous. Twice a year, in zones that observe daylight saving, an hour is either repeated or skipped entirely.

A job scheduled for 02:30 will not run at all on the day the clocks go forward, because 02:30 never occurs. On the day they go back, 02:30 happens twice, and whether the job runs once or twice depends on the implementation.

This is why so much scheduling infrastructure runs in UTC, which has no daylight saving and therefore no ambiguous or missing hours.

If a job must run at a particular local time, schedule it outside the 01:00 to 03:00 window where the transitions happen. If it must run exactly once, make it idempotent so a duplicate run is harmless.

Overlapping runs

Cron starts a job on schedule regardless of whether the previous run has finished. A task scheduled every five minutes that occasionally takes six will quietly end up with two copies running, and then three.

The consequences range from wasted resources to corrupted data, depending on what the job touches. It tends to appear under load, which is exactly when it does the most damage.

The fix is a lock the job takes on startup and releases at the end, exiting immediately if it cannot acquire one. On Linux, flock in the crontab line is the usual approach; most job frameworks have an equivalent.

*/5 * * * * /usr/bin/flock -n /tmp/job.lock /path/to/job.sh

The thundering herd at midnight

Scheduling everything at 0 0 * * * feels tidy and creates a spike. Every daily job on every machine starts in the same second, along with every daily job belonging to everyone else who reached for the same round number.

For jobs that call external APIs this is worse, because rate limits are hit by the whole population of callers at once. Public APIs see pronounced traffic spikes exactly on the hour.

Spreading jobs across the hour costs nothing. Picking a minute that is not zero, and varying it between jobs, flattens the load and makes failures easier to attribute.

Some schedulers support a random or hashed offset for exactly this reason, which spreads jobs deterministically without you having to choose a minute for each one.

Common questions

What do the five fields mean?

In order they are minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-6, where 0 is Sunday). An asterisk means every value. So "30 2 * * *" is 02:30 every day, and "0 9 * * 1" is 09:00 every Monday.

What is the difference between * and */1?

They select the same values, but they are not treated identically in the two day fields. An asterisk marks the field as unrestricted, while */1 marks it as restricted even though it matches everything. That distinction matters because of how cron combines day of month with day of week.

Why does my job with both a day of month and a weekday run more often than expected?

When both day fields are restricted, cron treats them as alternatives rather than requirements. "0 0 1 * 1" fires on the first of every month AND on every Monday, not only on a first that happens to be a Monday. To get the stricter behaviour you have to check the date inside the job itself.

Which time zone does a cron job use?

Traditional cron uses the system time zone of the machine it runs on. Most hosted schedulers, including Kubernetes CronJobs and the major CI providers, default to UTC. This page shows next runs in your browser time zone, so compare it against your server before relying on it.

What are @daily and the other macros?

They are shorthands most cron implementations accept: @yearly, @monthly, @weekly, @daily (also @midnight), and @hourly. They expand to ordinary expressions, so @daily is exactly "0 0 * * *". They read better, though they give you no control over the exact minute, which matters if many jobs share one.

Related tools

Other free tools that tend to come up in the same work.