Every Quarter Cron Expression
Runs on the 1st of Jan, Apr, Jul, and Oct at midnight.
0 0 1 1,4,7,10 * in POSIX cron
Expression
0 0 1 1,4,7,10 *Try it in the tester →Field Breakdown
How It Works
Month list `1,4,7,10` combined with day-of-month 1 — fires four times per year on the first day of each calendar quarter.
Example Run Times
- Jan 1 00:00:00
- Apr 1 00:00:00
- Jul 1 00:00:00
- Oct 1 00:00:00
- Jan 1 00:00:00 (next year)
Frequently Asked Questions
How do I shift to fiscal-year quarters starting in February?
Change the month list to `2,5,8,11`: `0 0 1 2,5,8,11 *` fires Feb 1, May 1, Aug 1, Nov 1.
0 0 1 1,4,7,10 * in Quartz / Spring
Four firings a year: midnight on January 1, April 1, July 1, and October 1. The step lives in the month field — */3 anchors at the field minimum, which for Quartz months is 1, so it selects months 1, 4, 7, and 10: the calendar quarters.
Quartz / Spring expression
0 0 0 1 */3 ?Try it in the tester →At 00:00:00 on day 1 of the month in Jan, Apr, Jul, Oct
Unix / POSIX equivalent: 0 0 1 1,4,7,10 *
Field Breakdown
Using It with Quartz / Spring
Quarter boundaries drive a distinct class of work: rolling forward quarterly table partitions, generating compliance and board reporting packets, resetting quarterly sales quotas and OKR counters. The string drops into @Scheduled(cron = "0 0 0 1 */3 ?") or a Quartz CronTrigger unchanged. With only four executions a year, treat each as an event rather than a routine tick — page on failure, and consider MISFIRE_INSTRUCTION_FIRE_ONCE_NOW semantics carefully, since the alternative to a late catch-up run is waiting three months.
Quartz-Specific Notes
- →Month steps anchor at 1, not 0, because the Quartz month field spans 1-12 — which is why */3 lands on Jan/Apr/Jul/Oct rather than some zero-based sequence.
- →Spelling it out as 1,4,7,10 (or JAN,APR,JUL,OCT) in the month field is equivalent and reads more obviously as "calendar quarters" to a reviewer.
- →January 1 is the year's most contested cron slot; if this shares a scheduler with new-year resets and the every-year crowd, an offset like 0 30 0 1 */3 ? sidesteps the pile-up while staying within the boundary day.
Frequently Asked Questions
Our fiscal quarters start in February — how do I shift the months?
Anchor the step at 2: 0 0 0 1 2/3 ? selects months 2, 5, 8, 11 — February, May, August, November — firing at midnight on the 1st of each.
Can I run on the last day of each quarter instead of the first?
Combine the L token with an explicit month list: 0 0 0 L 3,6,9,12 ? fires on March 31, June 30, September 30, and December 31 — Quartz resolves the correct last day per month.
Does */3 in the month field ever include December?
No. Starting from 1 and stepping by 3 yields 1, 4, 7, 10 and then stops (13 exceeds 12). December is only reachable by anchoring differently, e.g. 3/3 gives 3, 6, 9, 12.
0 0 1 1,4,7,10 * in AWS EventBridge
Four fires a year: 00:00 UTC on January 1, April 1, July 1, and October 1. The month field's */3 steps from the field minimum of 1, selecting months 1, 4, 7, and 10 — the openings of the four calendar quarters.
AWS EventBridge expression
cron(0 0 1 */3 ? *)Try it in the tester →At 00:00 UTC on day 1 of the month in Jan, Apr, Jul, Oct
Unix / POSIX equivalent: 0 0 1 1,4,7,10 *
Field Breakdown
Using It with AWS EventBridge
Quarterly triggers carry the compliance calendar: a Step Functions workflow that snapshots IAM users, roles, and access keys into an S3 evidence bucket for the quarterly access review, scheduled rotation reminders for credentials on a 90-day policy, or the export that opens each quarter's financial reporting cycle. With only four runs a year, treat each one as precious — attach a dead-letter queue, alarm on failure, and have the target write a completion marker that a follow-up check can verify, because the next natural retry window is three months away.
AWS-Specific Notes
- →*/3 in the month field always anchors at January; a fiscal year starting in February needs the start/step form 2/3 to hit February, May, August, and November.
- →Calendar quarters are not equal-length — Q1 is 90 or 91 days while Q3 is 92 — so "quarterly" here means calendar boundaries, not a fixed 91-day interval.
- →The January fire coincides with midnight UTC on New Year's Day; like any fire, it can arrive up to a minute late, which matters only if the job timestamps the new year itself.
Frequently Asked Questions
How do I run at the end of each quarter instead of the start?
Combine the last-day token with a month list: cron(0 0 L 3,6,9,12 ? *) fires at 00:00 UTC on March 31, June 30, September 30, and December 31 — L resolves to the true final day of each listed month.
Does */3 mean every three months from when I created the rule?
No. Cron steps are positional, not relative: */3 in the month field divides the calendar from month 1, so the fires are pinned to January, April, July, and October no matter when the rule was created.
Can a single quarterly fire be made more reliable?
The fire itself is at-least-once already; the fragile part is the target. Configure the rule's target with a dead-letter queue and retry policy, and alarm on the FailedInvocations metric so a botched quarter is caught the same day rather than next quarter.
0 0 1 1,4,7,10 * in GitHub Actions
Four runs a year: 00:00 UTC on January 1, April 1, July 1, and October 1. The */3 step in the month field starts counting from 1 — months run 1 through 12, unlike the zero-based hour field — which is exactly why it lands on calendar-quarter openings rather than March or some other offset.
GitHub Actions expression
0 0 1 */3 *Try it in the tester →At 00:00 UTC on day 1 of the month in Jan, Apr, Jul, Oct
Unix / POSIX equivalent: 0 0 1 1,4,7,10 *
Field Breakdown
Using It with GitHub Actions
Written as on: schedule: - cron: "0 0 1 */3 *" in a workflow on the default branch, quarterly cadence carries compliance-flavored work: rotating long-lived credentials on a 90-day policy, auditing dependency licenses before quarterly review, or archiving a quarter's worth of workflow artifacts and reports. With just four chances a year for the schedule to prove itself, treat workflow_dispatch as mandatory equipment — every change to the job should be exercised manually, because the next natural test window is three months out.
GitHub-Specific Notes
- →Step values in the month field begin at the field minimum of 1, producing months 1, 4, 7, 10 — the same syntax in the hour field would start at 0, a difference that surprises people moving expressions between fields.
- →On a public repository this schedule is structurally doomed without help: GitHub disables schedules after 60 days of repository inactivity, and the roughly 90-day gap between quarterly runs exceeds that limit — a dormant public repo will fire once and never again until someone re-enables it.
- →The January 1 tick lands at the precise turn of the UTC year, when many external services run their own maintenance — quarterly jobs touching third-party APIs may find New Year's the flakiest of the four runs.
Frequently Asked Questions
Why does */3 in the month field give January, April, July, October and not March, June, September, December?
Steps enumerate from the field's minimum, and months start at 1 — so the sequence is 1, 4, 7, 10. For end-of-quarter months write the list explicitly, 0 0 1 3,6,9,12 *, or use the offset range 3-12/3, which walks 3, 6, 9, 12.
My quarterly workflow ran in January but skipped April on a public repo — what gives?
Almost certainly the inactivity rule: public-repo schedules are suspended after 60 days without repository activity, and a quarter is about 90 days. Either ensure some activity lands between quarters, re-enable the workflow from the Actions tab each time, or drive the trigger from an external scheduler that calls the workflow_dispatch API.