Skip to content
d.devtul.fun
中文
Scheduling · 2026-09-20

Cron expressions, explained five fields at a time

The usual cron expression has five fields, separated by spaces:

┌───── minute (0-59)
│ ┌───── hour   (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌───── month (1-12)
│ │ │ │ ┌───── day of week (0-6, 0 = Sunday)
│ │ │ │ │
* * * * *

The crucial part: the five fields are combined with AND. A moment triggers the job only when all five match it.

What each field accepts

SyntaxMeaningExample
*Any value* in the hour field = every hour
5A specific value5 in minutes = the 5th minute of each hour
1-5A range1-5 in day of week = Monday to Friday
1,15A list1,15 in day of month = the 1st and the 15th
*/10A step*/10 in minutes = every 10 minutes
9-17/2A step inside a rangeIn hours = every 2 hours between 09:00 and 17:00

A few expressions you will actually meet

0 * * * *        every hour, on the hour
*/5 * * * *      every 5 minutes
0 3 * * *        every day at 03:00
0 3 * * 0        every Sunday at 03:00
0 0 1 * *        the 1st of every month at midnight
30 9 * * 1-5     weekdays at 09:30
0 */6 * * *      every 6 hours

The trap: day-of-month OR day-of-week

This is the least intuitive rule in cron. When both day-of-month and day-of-week are restricted — neither is * — most implementations, including Vixie cron and essentially every Linux distribution, treat them as an OR, not an AND.

0 0 1 * 1

Intuition says "midnight on the 1st of the month, when it is also a Monday". The actual meaning is "the 1st of the month, or any Monday". To express the AND you have to set one field to * and filter inside the job itself.

This rule catches a fresh batch of people every year, particularly on billing and reporting jobs where the date matters.

The other trap: time zones

Cron uses the server's local time zone. The same configuration deployed to two different regions can fire hours apart. On the day a daylight-saving transition happens, jobs inside the skipped hour may not run at all.

If timing matters, either standardise your servers on UTC and do the arithmetic yourself, or move to a scheduler that lets you name a time zone explicitly.

How to check what you wrote

The quickest way is to look at when it will actually run. The cron expression tool reads your expression back as a plain sentence and lists the next eight trigger times — the expression above reveals its real behaviour immediately.

Keep reading