Cron expression cheat sheet

A cron expression is five fields separated by spaces: minute, hour, day of month, month and day of week. 0 9 * * 1-5 means at 9:00 from Monday through Friday. This cheat sheet covers the syntax, the schedules people use most and the rules that surprise even experienced developers. Paste any expression into the generator on this page to read it in plain words and see its next run times.

6 min read

The five fields

Classic cron, as used by Linux crontab, Kubernetes CronJobs and GitHub Actions, reads five fields from left to right. Each field lists the values at which the job may run, and the job runs whenever all fields match the current time. An asterisk means any value.

PositionFieldAllowed valuesNames
1Minute0 to 59
2Hour0 to 23
3Day of month1 to 31
4Month1 to 12JAN to DEC
5Day of week0 to 7 (0 and 7 are Sunday)SUN to SAT

Try it here: Cron Expression Generator

Open the full tool page

Special characters

Four characters cover almost every schedule. They can be combined inside one field, for example 1-5,10 or 0-30/10.

CharacterMeaningExampleResult
*Every value* in the hour fieldEvery hour
,A list of values0,30 in the minute fieldAt minute 0 and 30
-A range9-17 in the hour fieldEvery hour from 9 through 17
/A step*/15 in the minute fieldEvery 15 minutes: 0, 15, 30, 45
/ after a valueStep from a start5/20 in the minute fieldAt minute 5, 25 and 45
@ shortcutA named schedule@dailySame as 0 0 * * *

Common schedules

These expressions were checked with the generator on this page. Copy the one closest to what you need and adjust the numbers.

ExpressionRuns
* * * * *Every minute
*/5 * * * *Every 5 minutes
*/15 * * * *Every 15 minutes
0 * * * *At the start of every hour
30 * * * *At minute 30 of every hour
0 */6 * * *Every 6 hours: 0:00, 6:00, 12:00, 18:00
0 0 * * *Every day at midnight
0 9 * * *Every day at 9:00
0 9,17 * * *Every day at 9:00 and 17:00
0 9 * * 1-5At 9:00 from Monday through Friday
*/10 9-17 * * 1-5Every 10 minutes during office hours on weekdays
0 22 * * 0,6At 22:00 on Saturday and Sunday
0 9 * * 1Every Monday at 9:00
0 0 1 * *On the first day of every month at midnight
0 0 1,15 * *On the 1st and 15th of every month
0 0 1 */3 *On the first day of every third month (quarterly)
0 0 1 1 *Once a year, on 1 January at midnight
15 2 * * *Every night at 2:15
0 12 * 6-8 *Every day at noon in June, July and August
0 8 1-7 * 1Careful: day 1 to 7 or any Monday, see below

Day of month and day of week together

This is the rule that catches the most people. When both day fields are restricted, classic cron runs on days that match either of them, not both. So 0 8 1-7 * 1 does not mean the first Monday of the month: it runs on days 1 to 7 and also on every Monday. In the same way, 0 0 13 * 5 runs on every 13th and on every Friday, not only on Friday the 13th.

There is one more twist: if one of the two fields starts with an asterisk, as in */2, cron treats it as unrestricted for this rule and both fields must match. 0 0 */2 * 1 therefore runs only on Mondays that fall on an odd day of the month. The generator on this page points out both cases in its explanation.

To run on the first Monday in classic cron, schedule the job for Mondays and let the script exit unless the day of the month is 7 or less. Quartz can express it directly with 2#1.

Time zones and daylight saving

Cron runs in the time zone of the machine or service that executes it. Many servers and cloud services use UTC, GitHub Actions schedules are always in UTC, and Kubernetes CronJobs use the controller's time zone unless you set the timeZone field. Some cron daemons also read a CRON_TZ variable in the crontab.

In zones with daylight saving time, one night a year has no 2:30 and another has 1:30 twice. Most Linux cron daemons run jobs from the skipped hour right after the change and run fixed time jobs only once in the repeated hour, while jobs that run every hour run in both. Other schedulers may skip the run instead. If a job must run exactly once a day, schedule it outside the hours between 1:00 and 3:00, or run the scheduler in UTC. The run list in the generator marks every run that falls on a clock change.

Seconds, Quartz and Spring

Java and some JavaScript schedulers add a seconds field at the start, so their expressions have six fields: 0 */5 * * * * runs every five minutes at second 0. Quartz goes further and changes several rules, which is why a classic expression often fails there.

  • Quartz has 6 or 7 fields: seconds, minute, hour, day of month, month, day of week and an optional year.
  • Days of the week are numbered 1 to 7 starting with Sunday, so MON is 2. Names such as MON-FRI avoid the confusion.
  • One of the two day fields must be ?, which means no specific value. 0 0 9 ? * MON-FRI runs at 9:00 on weekdays.
  • L means last: L in the day of month field is the last day of the month, 6L in the day of week field is the last Friday.
  • W picks the nearest weekday: 15W runs on the weekday closest to the 15th, LW on the last weekday of the month.
  • # picks the nth weekday: 6#3 is the third Friday of the month.
  • Spring's @Scheduled also uses six fields with seconds first, but numbers days of the week 0 to 7 like classic cron and does not require ?.

Mistakes to avoid

  • Writing * * * * * when you mean once a day. The first field is the minute, so this runs 1440 times a day.
  • Expecting */7 in the day of month field to mean every seven days. It means days 1, 8, 15, 22 and 29, and starts again on the 1st.
  • Scheduling day 31, 30 or 29. Months without that day are skipped, not moved to the last day.
  • Forgetting the time zone. 0 9 * * * on a UTC server runs at 9:00 UTC, which may be night where your users are.
  • Using Quartz features such as L or ? in a Linux crontab, or a five field expression in Quartz. The generator converts between the syntaxes when you switch.

Step by step

  1. Choose the syntaxPick Standard for crontab, Kubernetes and GitHub Actions, With seconds for schedulers that add seconds, or Quartz.
  2. Start from a scheduleClick one of the common schedules or paste your own expression into the Cron expression box.
  3. Adjust the fieldsUse the form to set each field to every value, every n, specific values or a range.
  4. Read the explanationCheck the sentence and the notes under the expression. They also warn about the day field rule.
  5. Check the next runsChoose your server's time zone and look at the next 10 runs before you copy the expression.

Frequently asked questions

How do I run a cron job every 5 minutes?

Use */5 * * * *. It runs at minute 0, 5, 10 and so on of every hour.

How do I run a job every weekday at 9 in the morning?

Use 0 9 * * 1-5. In Quartz the same schedule is 0 0 9 ? * MON-FRI.

Can cron run a job every 30 seconds?

Classic cron cannot go below one minute. Schedulers with a seconds field can, for example */30 * * * * *. In a crontab, a common workaround is two entries, one of them starting with sleep 30.

What is the difference between 0 and 7 in the day of week field?

Nothing in classic cron: both mean Sunday. Quartz uses 1 for Sunday and 7 for Saturday.

Why did my job run on a day I did not expect?

Most often because both day fields were set and cron ran on days matching either one, or because the server uses another time zone. Paste the expression into the generator to see both.

Is the expression sent anywhere when I test it?

No. The explanation and the run times are calculated in your browser.