Timestamps and scheduling guides
Month-end scheduling: avoid the day-31 trap
Select the actual last day of each month and verify dialect-specific L support before using it.
Day 31 is not month-end
A day-of-month value of 31 matches only months containing that date. It skips February, April, June, September and November.
Do not use this expression for a report that must run every month. Preview consecutive results to expose the gaps.
0 0 31 * *
Runs on January 31, then March 31; February is skipped.Confirm extension support
Some Cron implementations support L for the last day, while standard five-field crontab does not define that extension.
A parser accepting L is not proof that the deployed scheduler accepts it. Test the exact production dialect and version.
Use a portable daily guard when needed
A daily schedule plus an application calendar check can implement month-end without dialect extensions. Check whether tomorrow has a different month.
Construct tomorrow in the intended local calendar; adding 24 hours across a timezone transition is not always the same operation.
Schedule: 0 0 * * *
Application condition: local month(tomorrow) != local month(today)Separate month-end from business month-end
The last calendar day can be a weekend or holiday. The last business day needs an agreed holiday calendar and jurisdiction.
Record that calendar version and test February, a 30-day month and a holiday month-end. The site's date tools do not supply holiday data.