Cron expression for first day of every month

Free

0 0 1 * * - At 00:00, on the 1st.

Field by field

0 0 1 * * reads: At 00:00, on the 1st.

What each field of 0 0 1 * * selects
FieldValueSelects
Minute00
Hour000:00
Day of month11
Month*every month
Day of week*any day of the week

Worth knowing

  • Standard cron has no "last day of the month". Run on the 1st and process the previous month, or run on days 28-31 and have the job check whether tomorrow is the 1st.
  • Setting both day-of-month and day-of-week makes cron run when EITHER matches. 0 0 1 * 1 is the 1st and every Monday, not the first Monday.
  • @monthly is the same schedule.

Variations

  • 0 0 1,15 * *The 1st and the 15thExplain it
  • 0 9 1 */3 *09:00 on the first day of every quarterExplain it

The same schedule elsewhere

crontab

0 0 1 * * /path/to/job.sh

Runs in the machine's local timezone. crontab -e to edit.

GitHub Actions

on:
  schedule:
    - cron: "0 0 1 * *"

Always UTC. Nothing more often than every 5 minutes, and runs can start late when GitHub is busy.

Kubernetes CronJob

spec:
  schedule: "0 0 1 * *"
  timeZone: "Asia/Kolkata"

timeZone needs Kubernetes 1.27 or later; without it the controller's zone applies, usually UTC.

Spring @Scheduled

@Scheduled(cron = "0 0 0 1 * *")

Six fields: seconds come first. Days are written as names, which Spring and cron read alike.

Quartz

0 0 0 1 * ?

One of day-of-month and day-of-week must be ?. Quartz counts days 1-7 from Sunday, so names are safer than numbers.

AWS EventBridge

cron(0 0 1 * ? *)

Six fields, the last one the year. UTC unless the schedule sets a timezone. Days count from Sunday, as in Quartz.

systemd timer

[Timer]
OnCalendar=monthly
Persistent=true

Persistent=true runs a job that was missed while the machine was off, once it is back.