Cron Last Day of the Month
No classic one-liner exists — the honest 28–31 date-guard recipe with live next runs, plus the Quartz and EventBridge L forms.
History
Valid expressions you run are kept here — on this device only.
The plain-English description appears here.
| # | UTC | UTC time | DST |
|---|---|---|---|
| Upcoming runs for a valid expression appear here. | |||
—Press ? for shortcuts
Platform variants
Classic cron
Classic cron cannot express this — the five-field grammar has no last-day (L) token
Quartz
Cron expression: 0 0 0 L * ?
L in day-of-month means the month's last day.
AWS EventBridge
Cron expression: cron(0 0 L * ? *)
EventBridge supports Quartz-style L in day-of-month.
Kubernetes
Kubernetes cannot express this — CronJob schedules are plain five-field cron without L
GitHub Actions
GitHub Actions cannot express this — workflow schedules are plain five-field cron without L
Also covers: end of month
Do it offline:$ (crontab -l; echo '0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /path/to/job') | crontab -
How to use it
- Schedule the window: 0 0 28-31 * * wakes the job on the last four possible dates at midnight.
- Guard the body: run the work only when tomorrow is the 1st — the CLI line below bakes the check into the entry.
- On Quartz or EventBridge use the L token from the dialect list instead; Kubernetes and GitHub Actions have no equivalent.
Classic cron cannot say last day of the month: the five-field grammar has ranges and steps but no month-length awareness, and February ruins every fixed date. No pretending here — the recipe is a 28–31 window plus a one-line date guard, previewed for what the window really does.
Examples
0 0 28-31 * *describes At 00:00, between day 28 and 31 of the month
next 1 2026-08-28T00:00:00.000Z
next 2 2026-08-29T00:00:00.000Z
next 3 2026-08-30T00:00:00.000Z
next 4 2026-08-31T00:00:00.000Z
next 5 2026-09-28T00:00:00.000Z
note Classic cron cannot express "Last Day of the Month" in one line — these runs preview the stand-in expression "0 0 28-31 * *", not the exact intent.Previewed honestly: August wakes all four window dates; only the 31st is truly month-end. The engine's note rides along so the stand-in never passes for the intent.
0 0 31 * *describes At 00:00, on day 31 of the month
next 1 2026-08-31T00:00:00.000Z
next 2 2026-10-31T00:00:00.000Z
next 3 2026-12-31T00:00:00.000Z
next 4 2027-01-31T00:00:00.000Z
next 5 2027-03-31T00:00:00.000ZThe wrong shortcut: a fixed 31 silently skips September, November and February — the preview jumps August to October to December. Short months never match.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
How the guard turns 28–31 into month-end
The window fires up to four times a month; the guard keeps the run where tomorrow is the 1st — true only on the last day. February needs no special case: the 28th passes in common years, the 29th in leap years.
Common errors
Field 3 (day of month): "L" is Quartz syntax — L, W, # and ? do not exist in classic cron.- 0 0 L * * is the right idea on the wrong grammar — L belongs to Quartz and EventBridge's cron(), never crontab. The refusal marks the token; the guard recipe is the classic answer.
FAQ
Why not just schedule the 31st?
Five months lack one — a fixed 31 never fires in April, June, September, November or February. The worked example shows the skips; the guard recipe closes them.
What does the date guard actually check?
That tomorrow is the 1st — true once per month, on the final day, whatever its length. The escaped \% matters: unescaped percent signs split cron commands.
Which schedulers say this natively?
Quartz — 0 0 0 L * ? — and EventBridge's cron(0 0 L * ? *). Kubernetes and GitHub Actions read plain five-field cron and take the guard recipe; their dialect rows say so honestly.