What is a cron expression?
A cron expression is a compact scheduling string that tells a job scheduler exactly when to fire a task. The format was born in 1975 inside the Unix V7 cron daemon and has barely changed since — the same five-field grammar shows up today in Kubernetes CronJobs, AWS EventBridge, GitHub Actions workflows, Google Cloud Scheduler, GitLab CI, Jenkins pipelines, and the crontab binary still shipped with every Linux distribution. The grammar packs a lot of meaning into thirteen or so characters, which is why a parser that converts it into plain English is the difference between a confident deploy and a 3 AM rollback.
How does a cron expression work?
A standard cron expression has five space-separated fields that together define a repeating schedule. The engine checks the current wall clock against the expression every minute and fires the job when all five fields match. The fields, left to right:
- Minute (0–59). Which minute within the hour the job runs.
0means on the hour,30means at half past,*/5means every five minutes (00, 05, 10, ...), and15,45means at quarter past and quarter to. - Hour (0–23). Which hour of the day on the 24-hour clock.
0is midnight,9is 9 AM,17is 5 PM. Ranges (9-17for business hours) and step values (*/2for every other hour) work the same way as for minutes. - Day of month (1–31). Which calendar day to run.
1means the 1st of the month,*means every day,1,15means the 1st and the 15th. Be careful with31— it silently skips months that don’t have a 31st day. - Month (1–12 or JAN–DEC). Which months to run.
*means every month,1,7means January and July,1-3means Q1 only. Three-letter month names are case-insensitive in most implementations. - Day of week (0–7, where both 0 and 7 mean Sunday). Restricts firing to specific weekdays.
1-5is Monday through Friday,0,6is the weekend,MON-FRIworks in most parsers. When both day-of-month and day-of-week are set to specific values, classic cron fires on either match (logical OR), which surprises people every single time.
Why use a cron expression parser?
- Catch the silent misread before deploy. The expression `0 2 */3 * *` fires at 2 AM every third day, not every three minutes — paste it here and you’ll see that in plain English before it ships to production.
- Most cloud schedulers run in UTC by default. Previewing the next ten fire times in your local zone surfaces the off-by-one-hour DST drift before it pages someone at 3 AM.
- Shortcuts like `@daily`, `@weekly`, and `@monthly` are convenient but ambiguous. The parser shows you the underlying five-field form so you know exactly what got scheduled.
- The field-by-field builder lets you compose a schedule one column at a time and watch the human description update live, which is a lot faster than re-reading the cron man page for the tenth time.
Where are cron expressions used?
Cron syntax shows up anywhere a job needs to repeat on a clock. Three of the most common surfaces, with the exact gotcha each one is famous for:
- Backup schedules. The classic `crontab -e` entry that dumps a database to S3 at 2 AM nightly, or rotates a `pg_dump` archive on the 1st of every month. A line like `0 2 * * * /usr/local/bin/backup.sh` has shipped on more Linux servers than any other line of cron in history. Get the minute and hour right, redirect stderr somewhere durable, and you’ve replaced a manual checklist with a fire-and-forget script.
- GitHub Actions `schedule` triggers. The `on.schedule.cron` key in `.github/workflows/*.yml` accepts standard five-field cron, but the job always runs in UTC and GitHub will silently skip a fire-time if the runner queue is busy. Common pattern: `cron: '0 9 * * 1-5'` to send a Monday-through-Friday digest at 9 AM UTC. Preview it here in your local zone first so you don’t promise a 9 AM London digest that actually lands at 10 AM in BST.
- AWS EventBridge Scheduler. EventBridge cron expressions take a sixth field for the year and require `?` instead of `*` in either the day-of-month or day-of-week field — `cron(0 9 ? * MON-FRI *)` is the EventBridge translation of the classic weekday 9 AM standard cron. Used for scheduled Lambda invocations, ECS task runs, and Step Function state-machine starts; the misalignment with classic cron syntax is the number-one source of `ValidationException` errors in CloudFormation deploys.
What does a real cron expression look like?
Take 0 9 * * 1-5 — fires at 9:00 AM, every weekday. Reading the fields left to right: 0 is the zeroth minute of the hour, 9 is 9 AM on the 24-hour clock, * on day-of-month means every calendar day, * on month means every month, and 1-5 on day-of-week restricts the firing to Monday through Friday (where 1 = Monday in the standard cron numbering). Paste that into the input above and the parser confirms At 09:00 AM, Monday through Friday with the next ten fire dates rendered in whichever IANA zone you select. The same intent in AWS EventBridge syntax is cron(0 9 ? * MON-FRI *) — note the year field at the end and the ? where standard cron would use *. The same intent as a Quartz expression (six-field with leading seconds) is 0 0 9 ? * MON-FRI. Three different platforms, three different surface forms, one underlying schedule.
Cron expressions are unforgiving in exactly one way: a typo gives you a syntactically valid schedule that fires at the wrong time, with no error to catch in code review. Reading `0 0 1 * *` and knowing it runs at midnight on the 1st of every month, not on January 1st, takes practice. The parser above turns that practice into a ten-second sanity check — paste the expression, read the English, scan the next ten fire times in your local zone, and ship the YAML knowing the cron line actually does what the commit message says it does.
What is the difference between 5-field and 6-field cron?
Five-field cron is the classic Unix grammar with one-minute resolution. Six-field cron adds a leading seconds column for sub-minute scheduling — used by Quartz and Spring’s @Scheduled. AWS EventBridge also uses six fields, but its extra column is a trailing year, not seconds.
What do @hourly, @daily, and @weekly mean?
Vixie-cron nicknames introduced in 1987. @hourly = 0 * * * *, @daily = 0 0 * * *, @weekly = 0 0 * * 0, @monthly = 0 0 1 * *, @yearly = 0 0 1 1 *. @reboot fires once at boot. GitHub Actions and EventBridge reject these aliases.
Is Sunday day 0 or day 7 in cron?
Both, in classic Vixie cron — 0 and 7 are accepted so that ranges like 5-7 read naturally as Friday-to-Sunday. Monday is always 1, Saturday is always 6. Quartz and AWS EventBridge use a different convention: 1-7 with Sunday as 1. Check the platform docs before assuming.
How does cron handle daylight saving time?
Depends on the engine’s timezone. In UTC (the default on EventBridge, Kubernetes, and GitHub Actions) DST does not exist. In a local DST zone, classic Vixie cron skips jobs during the spring-forward gap and runs them twice during fall-back; systemd timers fire exactly once.