Toolman 100% local

Cron schedule examples

58 ready-made cron expressions, each with a field breakdown, the next scheduled runs and equivalents for GitHub Actions, Kubernetes and AWS EventBridge. Need something else? Build a custom expression.

ScheduleExpression
Every minute* * * * *
Every 2 minutes*/2 * * * *
Every 3 minutes*/3 * * * *
Every 4 minutes*/4 * * * *
Every 5 minutes*/5 * * * *
Every 6 minutes*/6 * * * *
Every 10 minutes*/10 * * * *
Every 12 minutes*/12 * * * *
Every 15 minutes*/15 * * * *
Every 20 minutes*/20 * * * *
Every 30 minutes*/30 * * * *
Every hour0 * * * *
Every 2 hours0 */2 * * *
Every 3 hours0 */3 * * *
Every 4 hours0 */4 * * *
Every 6 hours0 */6 * * *
Every 8 hours0 */8 * * *
Every 12 hours0 */12 * * *
Every day at 00:000 0 * * *
Every day at 01:000 1 * * *
Every day at 02:000 2 * * *
Every day at 03:000 3 * * *
Every day at 04:000 4 * * *
Every day at 05:000 5 * * *
Every day at 06:000 6 * * *
Every day at 07:000 7 * * *
Every day at 08:000 8 * * *
Every day at 09:000 9 * * *
Every day at 10:000 10 * * *
Every day at 11:000 11 * * *
Every day at 12:000 12 * * *
Every day at 13:000 13 * * *
Every day at 14:000 14 * * *
Every day at 15:000 15 * * *
Every day at 16:000 16 * * *
Every day at 17:000 17 * * *
Every day at 18:000 18 * * *
Every day at 19:000 19 * * *
Every day at 20:000 20 * * *
Every day at 21:000 21 * * *
Every day at 22:000 22 * * *
Every day at 23:000 23 * * *
Every weekday at 09:000 9 * * 1-5
Every weekend at 09:000 9 * * 6,0
Every Sunday at midnight0 0 * * 0
Every Monday at midnight0 0 * * 1
Every Tuesday at midnight0 0 * * 2
Every Wednesday at midnight0 0 * * 3
Every Thursday at midnight0 0 * * 4
Every Friday at midnight0 0 * * 5
Every Saturday at midnight0 0 * * 6
On the first day of every month0 0 1 * *
Every month0 0 1 * *
Every quarter0 0 1 1,4,7,10 *
Every year0 0 1 1 *
On the 15th of every month0 0 15 * *
Twice a day0 0,12 * * *
Every hour during business hours0 9-17 * * 1-5

The field layout

┌───────── minute        (0 - 59)
│ ┌─────── hour          (0 - 23)
│ │ ┌───── day of month  (1 - 31)
│ │ │ ┌─── month         (1 - 12)
│ │ │ │ ┌─ day of week   (0 - 6, Sunday = 0)
│ │ │ │ │
* * * * *

Shorthand aliases

@yearly / @annually0 0 1 1 *
@monthly0 0 1 * *
@weekly0 0 * * 0
@daily / @midnight0 0 * * *
@hourly0 * * * *
@rebootonce at startup

Day-of-month and day-of-week are OR, not AND

This is the one that catches everybody. When both the day-of-month and the day-of-week fields are restricted — neither is * — cron runs the job when either matches, not when both do.

0 0 1 * 1     # not "the 1st, if it is a Monday"
              # it is "the 1st" OR "every Monday"

So that expression fires on the first of every month and on all four or five Mondays as well — roughly six times a month rather than the once you were picturing. It is specified behaviour, not a bug: POSIX says so and Vixie cron, the one behind most Linux systems, implements it.

When only one of the two is restricted the surprise disappears, which is why it stays hidden until the day you need "the first Monday of the month" — an expression standard cron cannot write at all. The usual answer is 0 0 1-7 * 1, which fires on every Monday and on the 1st to 7th, and then a guard inside the job checks the date.

What the step syntax actually counts from

*/5 in the minute field means minutes 0, 5, 10 and so on — it steps through the field's own range, not from whenever the job was installed. A job set to */5 at 09:03 first runs at 09:05, not 09:08.

Steps also apply to a range: 0-30/10 is minutes 0, 10, 20 and 30. And a step that does not divide the range evenly simply stops early rather than wrapping — */7 in the hour field gives 0, 7, 14 and 21, then a five-hour gap over midnight.

Cron has no timezone of its own

Jobs run in the system's local time, which means a schedule crossing a daylight-saving boundary either runs twice or not at all. Vixie cron treats jobs in the skipped hour as due immediately when the clock jumps forward, and jobs in the repeated hour as already run; other implementations differ, and container schedulers usually run UTC regardless of the host.

The reliable fix is to set the timezone explicitly where the scheduler allows it — CRON_TZ=UTC at the top of a crontab, timeZone in a Kubernetes CronJob, or the schedule expression's own timezone field in EventBridge — and to keep anything that must not run twice out of 01:00–03:00 entirely.

Five fields, unless it is six

Standard Unix cron takes five fields, starting at minutes. Quartz and Spring's scheduler take six, starting at seconds, so an expression copied between them is shifted by one place and silently means something else. 0 0 12 * * ? is noon in Quartz. Paste it into a crontab and Unix cron reads the first five fields as the schedule and everything after them as the command — so it becomes a job that runs at 00:00 on the 12th of every month and tries to execute a program called ?. It is accepted, it is scheduled, and it fails somewhere you are not looking, which is worse than a syntax error would have been.

Quartz also adds characters standard cron does not have — L for last, W for nearest weekday, # for "the nth weekday of the month". 0 0 12 ? * 2#1 is the first Monday of the month, which is the expression standard cron cannot express. If a snippet contains any of those, it is not a Unix crontab line.