How to Read a Cron Expression (With Examples)
A cron expression is five terse fields that together say "run at these times." The syntax is compact enough to misread at a glance, which is exactly how a job meant for 3 AM once a day ends up firing every minute instead. Here's how to actually parse one.
The five fields, in order
Reading left to right, a standard cron expression is: minute (0–59), hour (0–23), day-of-month (1–31), month (1–12 or JAN–DEC), day-of-week (0–6 or SUN–SAT, where both 0 and 7 mean Sunday). Some schedulers add a leading seconds field, making six in total. The shorthand aliases @yearly, @monthly, @weekly, @daily and @hourly each stand in for a common five-field expression, if a scheduler supports them.
Stars, ranges, lists and steps
*— every possible value of that field.5— exactly that one value.1-5— an inclusive range (Monday through Friday, in the day-of-week field).1,15,30— a specific list of values.*/15— a step: every 15th value starting from the field's minimum, so minutes 0, 15, 30, 45.9-17/2— a step within a range: 9, 11, 13, 15, 17.
Worked examples
0 9 * * 1-5— 9:00 AM, Monday through Friday.*/5 * * * *— every 5 minutes, all day, every day.0 0 1 * *— midnight on the 1st of every month.30 3 * * 0— 3:30 AM every Sunday.0 0 * * *— midnight every day.
The gotcha that catches almost everyone
If both day-of-month and day-of-week are restricted at the same time (neither one is a bare *), cron runs the job whenever either field matches — not only when both match together. So 0 0 13 * 5 fires on the 13th of every month and on every Friday, which is rarely the intersection people expect when they write an expression like that. If you only want "the 13th, but only if it's also a Friday," a plain cron expression can't say that on its own; you'd need extra logic in the job itself.
*/5 in the hour field means "every 5 hours from midnight" (0, 5, 10, 15, 20), not "every 5 minutes" — the step always applies to that field's own unit. And a bare number in the day-of-week field is 0 for Sunday, so 1 is Monday, not "the first day."Time zone: whose clock counts
A cron expression carries no time zone information of its own — it runs in whatever time zone the machine executing it is set to, whether that's a physical server, a container, or a CI runner. This is a common source of "my job ran an hour off" surprises around daylight-saving transitions, and it's also why the exact same expression can fire at a different wall-clock moment depending on where it's deployed.
Frequently asked questions
What does 0 9 * * 1-5 mean?
At minute 0 of hour 9 (9:00 AM), every day of the month, every month, on Monday through Friday — in other words, 9 AM on weekdays.
What's the difference between */5 in the minute field and the hour field?
In the minute field, */5 means every 5 minutes (0, 5, 10, 15...). In the hour field, the same */5 means every 5 hours starting from midnight (0, 5, 10, 15, 20) — the step always applies to that field's own unit.
Why did my job run on both the 13th and every Friday?
When both day-of-month and day-of-week are restricted (neither is a star), cron runs the job whenever either one matches, not only when both match at once.
What time zone does a cron job run in?
Whatever time zone the machine actually running it is set to — the server, container or CI runner — not necessarily the time zone of whoever wrote the expression.