What is a cron expression?
A cron expression is a short string that tells a scheduler when to run a job. Five fields, separated by spaces, describe the minute, hour, day of the month, month and day of the week. The expression 30 2 * * 1 means half past two in the morning, every Monday.
The format comes from Vixie cron, the scheduler that ships with almost every Linux distribution. The same five-field syntax turns up far beyond the crontab file: in Kubernetes CronJobs, GitHub Actions workflows, AWS EventBridge rules, Jenkins pipelines, Laravel and Django scheduled tasks, and the cron settings of most hosting control panels. Learn it once and it follows you around.
It is also easy to get subtly wrong, which is why the [msm_tool slug="cron-expression-builder"] shows you the next run times rather than just accepting what you typed.
The five fields, in order
| Position |
Field |
Allowed values |
| 1 | Minute | 0–59 |
| 2 | Hour | 0–23 |
| 3 | Day of month | 1–31 |
| 4 | Month | 1–12, or JAN–DEC |
| 5 | Day of week | 0–7, or SUN–SAT |
Both 0 and 7 mean Sunday in the day-of-week field. That redundancy is deliberate and dates back to disagreements between early cron implementations about where the week starts.
Special characters you can use in each field
- Asterisk
* — every value. In the hour field it means every hour.
- Comma
1,15,30 — a list of specific values.
- Hyphen
9-17 — an inclusive range, nine through seventeen.
- Slash
*/15 — a step. Every fifteenth value, so minutes 0, 15, 30 and 45.
Steps combine with ranges. 0-30/10 in the minute field fires at 0, 10, 20 and 30, then stops until the next hour.
How to build a cron expression
- Pick a starting point from the common schedules list, or type an expression straight into the top field.
- Adjust any of the five pickers. They stay in step with the expression field, so editing either one updates the other.
- Press Explain & preview. You get a plain-English reading of the schedule and the next run times, so you can confirm the expression means what you intended before it goes anywhere near a server.
- Copy the expression into your crontab, workflow file or control panel.
Everything runs in your browser. No expression is sent anywhere, which matters more than it sounds — cron lines often reveal internal hostnames, script paths and deployment timings.
Common cron schedules
| Expression |
When it runs |
* * * * * | Every minute |
*/5 * * * * | Every five minutes |
0 * * * * | Every hour, on the hour |
0 */6 * * * | Every six hours |
0 3 * * * | Daily at 03:00 |
30 9 * * 1-5 | Weekdays at 09:30 |
0 0 * * 0 | Weekly, Sunday at midnight |
0 0 1 * * | Monthly, on the first |
0 0 1 1 * | Yearly, on 1 January |
The day-of-month and day-of-week trap
This is the single most common cron mistake, and it catches experienced engineers.
When you restrict both the day-of-month field and the day-of-week field, cron runs the job when either matches — not when both do. So 0 0 1 * 1 does not mean "the first of the month, but only if it is a Monday." It means "the first of every month, and also every Monday." That is roughly five runs a month instead of the one you expected.
If either field is an asterisk, the rule does not apply and everything behaves as you would expect. The builder honours this behaviour rather than glossing over it, so the preview shows the real run times, including the ones you did not intend.
Cron and clock changes
Daylight saving is where schedules quietly misbehave. When clocks jump forward, an hour of local time simply does not exist, so a job scheduled inside that window has no valid minute to run in. When clocks go back, the hour repeats.
Different schedulers resolve this differently, and the safest habit is to run servers on UTC and keep anything time-critical away from the small hours. The preview works out run times in your own browser's timezone by walking real local dates, so a schedule that falls into a clock-change gap is shown skipping it rather than firing an hour late.
What this syntax does not include
The five-field format is not the only cron dialect, and mixing them up produces expressions that are rejected or, worse, silently misread.
- Seconds. Some schedulers, notably Quartz and Spring, put a seconds field first, making six fields. Standard crontab has no seconds field — one minute is the finest resolution.
- Year. Quartz allows an optional seventh field for the year. Vixie cron does not.
- The
L, W and # extensions. Quartz uses these for "last day of month", "nearest weekday" and "nth weekday". They are not part of this syntax.
- Shorthand macros. Many crons accept
@daily, @hourly and @reboot. These are handled by the cron daemon rather than the expression parser, so support varies by platform.