Cron expression for every quarter

0 0 1 1,4,7,10 *

The job runs four times a year, at 00:00 on 1 January, 1 April, 1 July and 1 October.

Runs when: minute 0; hour 0; day of month 1; in Jan, Apr, Jul, Oct; any day of week.

Change it in the cron expression generator

How the five fields read

FieldValueReads as
Minute0at 0
Hour0at 0
Day of month1at 1
Month1,4,7,10at January, April, July, October
Day of week*every value

The next five runs

What people use it for

Cron has no idea what a quarter is

You list the months yourself. 0 0 1 */3 * gives the same four dates, because */3 in the month field counts from January. If your fiscal year starts in another month, write the months out, for example 4,7,10,1 for a year that starts in April. The schedule is then easy to get wrong without noticing, so check the dates with the next-run list.

Variations of every quarter

ExpressionWhat it does
0 0 1 */3 *The same four dates, written with a step in the month field.
0 0 1 3,6,9,12 *The 1st of March, June, September and December.
0 9 1 1,4,7,10 *The start of each quarter, at 09:00 instead of midnight.

The same schedule in four tools

Linux crontab

0 0 1 1,4,7,10 * /path/to/command

Add it with crontab -e. It runs in the machine's time zone.

Kubernetes CronJob

spec:
  schedule: "0 0 1 1,4,7,10 *"
  timeZone: "Etc/UTC"
  concurrencyPolicy: Forbid

timeZone is stable from Kubernetes 1.27. Without it, the controller's time zone applies. Forbid stops a new run starting while the last one is still going.

GitHub Actions

on:
  schedule:
    - cron: '0 0 1 1,4,7,10 *'

Schedules run in UTC from the default branch, and a run can start a few minutes late when GitHub is busy. Scheduled workflows in public repositories are disabled after 60 days without repository activity.

AWS EventBridge

cron(0 0 1 1,4,7,10 ? *)

EventBridge uses six fields, with a question mark in one of the two day fields, and rules run in UTC. Weekday numbers start at Sunday = 1, so names such as MON are safer than numbers.

Questions about every quarter

Why does the month field say 1,4,7,10 and not 0,3,6,9?
Cron numbers months from 1 to 12. That differs from JavaScript, which counts months from 0, and the mix-up causes real off-by-one mistakes.
How do I run on the last day of each quarter?
Cron has no last-day syntax. Run 0 0 28-31 3,6,9,12 * and have the script check that tomorrow is the 1st, or on AWS EventBridge use cron(0 0 L 3,6,9,12 ? *).

Nearby schedules

Scheduling jobs, pipelines and cloud infrastructure is part of my DevOps engineering work.