Cron Expressions in Plain English: From "*/5 * * * *" to Weekdays at 9:00
"Let the report be assembled every morning at nine" — and the scheduler settings end up with the cryptic "0 9 * * *". Cron has been around for half a century, and its syntax hasn't gotten any friendlier. But really all the magic is five space-separated fields. Time to learn to read them.
Five fields: minute, hour, day, month, day of week
Left to right: minute (0–59), hour (0–23), day of month (1–31), month (1–12), day of week (0–7, where both 0 and 7 mean Sunday). The asterisk means "every value of this field." The entry "0 9 * * *" reads: zero minutes, the ninth hour, any day — that is, every day at 09:00.
*/5 * * * * — every 5 minutes
0 9 * * 1-5 — weekdays at 9:00
0 9 1 * * — 1st of every month at 9:00
30 8 * * 0 — Sundays at 8:30
0 0 1 1 * — once a year, January 1 at midnightThe special characters you'll see most often
- comma — a list of values: "0,15,30,45" — at the 0th, 15th, 30th, and 45th minute;
- hyphen — a range: "9-17" — from nine to seventeen hours;
- slash — a step: "*/10" — every 10 units; "10-40/5" — from 10 to 40 in steps of 5.
The time zone pitfall
A server's cron runs on the machine's system time, and on most servers that's UTC. "Every day at 9:00" UTC is noon in Berlin in winter and one in the afternoon in summer. If a job must fire on local time, either set the server's time zone properly or pick the hour with the offset factored in — and always check the actual time of the first run.
How to check a schedule in advance
You don't have to wait for midnight to learn whether "30 8 * * 0" will fire (spoiler: that's Sunday, 8:30). Paste the expression into the cron parser: it translates it into human language and lists the next few runs — you can see at once whether what you meant matches what you wrote.