Cron: Last Day of the Month
Standard POSIX cron has no direct way to say "last day of the month" — months have different lengths (28 to 31 days), and cron's day-of-month field only understands fixed numbers or ranges, not relative positions. The common workaround is 0 0 28-31 * * combined with a same-day check inside the job itself.
0 0 28-31 * *
Examples & Variations
Common Mistakes
- Assuming 0 0 31 * * runs on the last day of every month — it only fires in months that actually have 31 days, silently skipping February, April, June, September, and November.
- Copying Quartz's L syntax (0 0 L * ?) into a standard Linux crontab — Vixie cron and most POSIX cron daemons don't support L at all and will reject the entry or behave unpredictably.
- Forgetting to guard the 28-31 workaround with an actual date check — without it, the job runs on every one of those days, not just the true last day.
Best Practices
- The most portable standard-cron workaround: schedule 0 0 28-31 * * and add a check in your script — e.g. compare tomorrow's date to see if it rolls into a new month — and exit immediately if today isn't actually the last day.
- If your scheduler is Quartz, AWS EventBridge, or another system that supports the L character, use 0 0 L * ? directly instead of the day-range workaround — it's cleaner and unambiguous.
- Consider whether 'first day of next month' (0 0 1 * *, run one day later) achieves the same practical goal — it's often simpler than true last-day-of-month logic.
Frequently Asked Questions
- Why can't standard cron express 'last day of the month' directly?
- Cron's fields only support fixed values, ranges, steps, and lists — none of which can express a relative concept like 'the final day,' since that day's number (28, 29, 30, or 31) changes depending on the month and leap year.
- What is the L character in Quartz Scheduler?
- Quartz (and AWS EventBridge, which uses Quartz-style cron) extends the day-of-month field with L, meaning 'last day of the month.' 0 0 L * ? runs at midnight on the last day, whatever it is that month — but this only works in Quartz-compatible schedulers, not standard Linux cron.
- What's the simplest reliable workaround for standard cron?
- Run daily (or on 28-31) and check the date programmatically: in most languages, adding one day to today and checking if the month changed tells you unambiguously whether today is the last day of the month.
Related Tools
Cron Parser
Translate cron expressions to plain English
Cron Cheat Sheet
Quick reference for cron syntax, special characters, and shortcuts
Cron Examples Library
Browse and search common cron expression examples
Cron: First Day of the Month
The cron expression for the first day of every month is 0 0 1 * *. See scheduling examples for billing, reports, and monthly resets.
Cron: Every Midnight
The cron expression for every midnight is 0 0 * * *, running once daily at 00:00. See midnight scheduling examples and best practices.
Cron: Every Noon
The cron expression for every noon is 0 12 * * *, running once daily at 12:00 PM. See noon scheduling examples and best practices.