For Developers
A cron schedule looks like a cryptic string of asterisks and numbers. Underneath, the actual mechanism is simpler than it looks.
Cron is one of the oldest scheduling systems still in everyday use, and its five-field syntax hasn't changed much since it first appeared in Unix systems in the 1970s. It looks cryptic mostly because it's dense, not because the underlying idea is complicated.
A cron daemon isn't counting down to your next scheduled job. It's doing something much simpler: once every minute, it wakes up, checks the current minute, hour, day, month, and weekday against every scheduled entry, and runs anything that matches. That's the entire mechanism — there's no advance scheduling or queueing involved, just a check that happens 1,440 times a day.
The five fields, in order, are minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-6, where both 0 and 7 usually mean Sunday). An asterisk means "any value matches this field." So 0 9 * * * matches minute 0, hour 9, any day, any month, any weekday — which is just "every day at 9:00."
When both the day-of-month and day-of-week fields are restricted at the same time, cron treats them as an OR, not an AND. A schedule like 0 9 15 * 1 doesn't mean "the 15th, if it's a Monday" — it means "every 15th of the month, AND every Monday," which is a very different (and much more frequent) schedule than most people expect on first read. This single detail is responsible for a disproportionate number of "why did this job run today" support tickets.
Cron typically evaluates time in the system's local timezone, unless the daemon or the specific job is explicitly configured otherwise. On a server that's been set to UTC (common for cloud infrastructure), "daily at 9 AM" means 9 AM UTC — which is a different local time entirely for whoever's actually reading the output. It's worth checking explicitly rather than assuming.
If you want to build or double-check a schedule without doing the field logic by hand, the Cron Expression Builder & Explainer parses an expression into plain English and shows the next several real run times.
Related
Build a schedule or decode an existing one, with next run times.
Check what a scheduled run time looks like in another zone.
Convert timestamps used by systems your jobs might touch.