Skip to content

Every year cron: what @yearly means and whether you should rely on it

Runs in your browser — nothing you paste leaves this page. How we prove that

Cron Expression Tester playground

Example

Five fields — minute, hour, day of month, month, day of week. Macros like @daily are supported too.

Results update as you type — press Enter to run now.

Timezone
fig. 04 — cron-expression-tester · scheduling Valid
Result

At 00:00, on the 1st of the month, in January.

Minute0
Hour0
Day of month1
Month1
Day of week*
Next runs
  • Computed in your browser, in your timezone.

`@yearly` (also spelled `@annually`) is shorthand for `0 0 1 1 *`, a single run at midnight on 1 January. The engine expands it and reads it as: At 00:00, on the 1st of the month, in January.

What @yearly expands to

Minute 0, hour 0, day of month 1, month 1, any day of week: 0 0 1 1 *. The month field can also be written by name, so 0 0 1 JAN * is the same schedule. @annually is an exact synonym.

This page's parser expands the macro and reads it as: At 00:00, on the 1st of the month, in January. The next run times in the panel above are computed in your browser, in your own timezone, so they are not printed in this text.

Should a job run once a year?

Yearly cron entries exist for things like archiving the previous year's logs, rotating a long-lived key, or resetting annual counters. They are also the entries most likely to fail unnoticed: the server may have been rebuilt, the script's dependencies upgraded or the crontab dropped during a migration since the last run, and nobody will see the result until the next January.

Treat a yearly job like a manual runbook with a reminder attached. Make it idempotent and runnable by hand for a named year (/opt/ops/bin/archive-year 2025), log loudly, and have something outside the host, such as a dead-man's-switch check, alert if the run does not report in. For certificates and keys, expiry monitoring is safer than a yearly rotation job.

New Year in which timezone?

Midnight on 1 January is midnight in the cron daemon's zone. On a UTC server that is 05:30 on 1 January in India and still the evening of 31 December in the Americas, which matters if the job decides which year it is closing. Pass the year explicitly, or keep the server on UTC and make the job's notion of a year UTC as well.

Plain cron does not catch up: if the machine is off at that minute, the year's only run is lost. A systemd timer with Persistent=true, or anacron, runs it at the next boot.

systemd, Kubernetes and GitHub Actions

systemd's OnCalendar=yearly (or annually) is *-01-01 00:00:00, the same moment as cron's. Kubernetes accepts @yearly, @annually or 0 0 1 1 *. GitHub Actions requires the five-field form, cron: '0 0 1 1 *', in UTC, and a scheduled workflow in a public repository with no activity for 60 days is disabled, which a once-a-year job will certainly hit. Related macros: @monthly and @weekly.

FAQ

Questions, answered.

Tap a question to expand the answer.

None. Both are defined as 0 0 1 1 *, midnight on 1 January, in every cron implementation that supports macros.

Yes, with the five-field form. For example 0 3 15 4 * runs at 03:00 on 15 April every year.

More free, private DevOps tools.

The Cron Expression Tester is one tool in OpsCanopy — a growing canopy of browser-based validators, converters and testers that never touch a server.

New to Linux?  Read the Linux guide →

42 free tools, every one offline-capable — opscanopy.com works with no signup and nothing uploaded.

Scheduling on Linux? Pair this with the Cron to systemd Converter, or browse the full tools directory.

Not affiliated with or endorsed by any cron implementation. Format names are used only to describe what this tool reads. OpsCanopy is free and open.