The expression
0 0 1 1 *
Runs once a year, at 00:00 on 1 January. The @yearly and @annually macros mean exactly this.
| Field | Value | Meaning |
|---|---|---|
| Minute | 0 |
at minute 0 |
| Hour | 0 |
at midnight |
| Day of month | 1 |
the 1st |
| Month | 1 |
January |
| Day of week | * |
any day of the week |
Standard cron has no year field, so "once a year" means one fixed date in the month and day-of-month fields. To run on any other date, change those two: 30 June at 18:00 is 0 18 30 6 *.
Variants
| Schedule | Expression |
|---|---|
| 1 January at 6am | 0 6 1 1 * |
| 31 December at 23:00 | 0 23 31 12 * |
| 1 April (start of a fiscal year) | 0 0 1 4 * |
| Twice a year | 0 0 1 1,7 * |
| Every quarter | 0 0 1 1,4,7,10 * |
| Every month | 0 0 1 * * |
| 29 February (leap years only) | 0 0 29 2 * |
0 0 29 2 * really does run only every four years (more precisely, in leap years), because cron skips dates that don't exist. That's correct behaviour, but rarely what a "yearly on the 29th" job wants. Use the 28th, or 1 March.
Where to write it
- crontab (Linux, macOS):
@yearly commandor0 0 1 1 * commandincrontab -e, in the server's time zone. A server that is off or rebooting at midnight on New Year's Day misses the run for a whole year; anacron (an/etc/anacrontabline with a period of365days) or a systemd timer withOnCalendar=yearlyandPersistent=truecatch up instead. - GitHub Actions:
cron: '0 0 1 1 *'in UTC, so it fires on the afternoon or evening of 31 December across the Americas. GitHub disables scheduled workflows in public repositories after 60 days without activity, so in a quiet repo a yearly workflow will usually be off by the time it's due. - Kubernetes CronJob:
schedule: "@yearly"or"0 0 1 1 *", withtimeZone:so New Year is your New Year. - AWS EventBridge:
cron(0 0 1 1 ? *). EventBridge has a sixth field for the year, so a one-off on a single date is also possible:cron(0 0 1 1 ? 2027).
Common mistakes
0 0 * 1 *runs every day in January.0 0 1 * *is monthly, not yearly.- Year-boundary bugs in the job itself. A job at 00:00 on 1 January that computes "this year" gets the new year. If it should close out the year that just ended, compute the previous year, or run at
0 23 31 12 *. - Testing once a year. Run the command by hand after every change; you won't see the schedule fire for months.
See the next runs in the Cron Expression Parser.