Cron on the last day of the month

0 0 L * *

0 0 L * * runs a job at 00:00 on the last day of every month, whether that’s the 28th, 29th, 30th or 31st. L in the day-of-month field means “last”. This tool reads it, and so do Quartz, AWS EventBridge, Spring and croner, but the crons on most Linux servers don’t.

When it fires

Checked on October 14, 2026, the next five runs are:

Oct 31  Nov 30  Dec 31  Jan 31  Feb 28    (all at 00:00)

February gets the 28th in 2027 and the 29th in 2028, a leap year.

Where L doesn’t work

Vixie cron (the cron package on Debian and Ubuntu) and cronie (Fedora, RHEL) refuse to install the line, and neither Kubernetes nor GitHub Actions takes it. The classic workaround runs on every day that can be the last one and lets the shell check whether tomorrow is the 1st:

0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /usr/local/bin/close-month.sh

Cron fires on the 28th to the 31st (October 28, 29, 30 and 31, then November 28), and the test passes only on the 31st. The backslash matters: cron turns a bare % into a newline, and +\%d reaches the shell as +%d. date -d is GNU; on macOS and the BSDs, write date -v+1d +\%d instead. Both, checked against fixed dates:

date -d '2026-10-31 tomorrow' +%d              # 01: GNU, the job runs
date -d '2028-02-28 tomorrow' +%d              # 29: a leap year, it waits a day
date -j -v+1d -f %Y-%m-%d 2026-10-31 +%d       # 01: BSD, the job runs

The start of the last day

0 0 L * * runs as the last day begins, with a whole day of the month still to come. A month-end job that needs the full month runs late on the last day, 0 23 L * *, or at 00:00 on the 1st, 0 0 1 * *, and works on the month that just ended.

The same schedule elsewhere

  • crontab: the 28-31 line above, since Vixie cron and cronie have no L.
  • GitHub Actions: cron: '0 0 28-31 * *', with the date check in the job; YAML needs no backslash before %.
  • Kubernetes CronJob: schedule: "0 0 28-31 * *", with the date check in the container’s command. The API server rejects L.
  • AWS EventBridge: cron(0 0 L * ? *).
  • systemd timer: OnCalendar=*-*~01 00:00. A ~ counts days back from the end of the month, so ~01 is the last day.
  • Spring @Scheduled: 0 0 0 L * *.

Try it in the Cron Builder

At 00:00, on the last day of the month

Read as a crontab line, where Sunday is 0 or 7.

minutehourday of monthmonthday of week
00L**

Next runs

Working out the next runs from your clock…

Runs in your browser. Nothing you enter is sent anywhere.