0 0 28-31 * *
Open in the generator
Five-field cron cannot express "last day of the month" because month lengths differ. The standard workaround schedules the job on every possible last day and lets the command test the date:
0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/job
The percent sign must be escaped as \% inside a crontab, because an unescaped % is treated as a newline. On macOS and BSD, date -d is not available; use date -v+1d +%d instead. Schedulers with an extended syntax (Quartz, Jenkins, some cloud schedulers) support L in the day-of-month field, which means "last".
Field by field
| Value | Field | Meaning |
|---|---|---|
| 0 | Minute 0–59 | at minute 0 |
| 0 | Hour 0–23 | at 00:00 |
| 28-31 | Day of month 1–31 | 28 to 31 |
| * | Month 1–12 or JAN–DEC | every month |
| * | Day of week 0–7 or SUN–SAT (0 and 7 are Sunday) | every day of the week |
Next run times
Computed in your browser from the current time, so you can check the schedule against a clock you trust.
Your timezone (local)
- Needs JavaScript.
UTC (GitHub Actions, Kubernetes default)
Variations
0 0 1 * *first day of the month, often a simpler alternative · see page0 23 28-31 * *the same guard, late evening · try it0 0 L * *Quartz / extended syntax only · try it
Where this expression works
- Linux and macOS crontab: as written; times follow the system timezone.
- Kubernetes CronJob: the same five fields; UTC unless
spec.timeZoneis set. - GitHub Actions: the same syntax in UTC, minimum interval five minutes, no
@shortcuts. - AWS EventBridge: a different six-field syntax; do not paste this expression unchanged.
Full platform comparison · Cron tutorial
FAQ
Why not just run on the 31st?
Only seven months have 31 days; the job would never run in April, June, September, November or February.
Can I run on the last Friday of the month?
Same technique: schedule every Friday and have the script exit unless date +%d is 25 or greater (the last seven days).