Run a cron job on the last day of the month

0 0 0 L * ? Check it below, then take the line for any of 17 schedulers.

Click to edit · paste a crontab line · hover a field for its values

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

 

Nothing to watch out for on Quartz.

Trigger
TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 L * ?")
        .inTimeZone(TimeZone.getTimeZone("UTC")))
    .build();

Details

Upcoming runs
Calendar 12 days a year
Between two dates
Daylight saving

When things go wrong Server off: Fires once when it can (smart misfire policy), if the job store survived
Server was off
Fires once when it can (smart misfire policy), if the job store survived. The default RAM store doesn't.
Last run still going
Runs concurrently, unless the job has @DisallowConcurrentExecution.
A run fails
Logged. The trigger keeps its schedule. No retry.
Time zone
The JVM's zone, or inTimeZone() on the trigger.
Precision
1 second.

Sources: github.com,github.com

Other schedulers As written in 1 of 16
  • ↻ Debian / Ubuntu cron 0 0 28-31 * * [ "$(date -d '+1 day' +\%d)" = 01 ] && … Debian / Ubuntu cron takes 5 fields: minute hour day month weekday. vs RunWisp
  • ↻ cronie 0 0 28-31 * * [ "$(date -d '+1 day' +\%d)" = 01 ] && … cronie takes 5 fields: minute hour day month weekday. vs RunWisp
  • ✗ BusyBox crond BusyBox crond takes 5 fields: minute hour day month weekday. BusyBox crond can't run this: it has no last-day or nearest-weekday syntax.
  • ↻ systemd timer *-*~01 00:00:00 UTC systemd timer uses OnCalendar=, not cron lines. vs RunWisp
  • ↻ RunWisp 0 0 28-31 * * [ "$(date -d '+1 day' +%d)" = 01 ] && … RunWisp takes 5 fields, or 6 with seconds first.
  • ✗ Kubernetes CronJob Kubernetes CronJob takes 5 fields: minute hour day month weekday. Kubernetes CronJob can't run this: it has no last-day or nearest-weekday syntax.
  • ✗ Ofelia Ofelia doesn't take L for the last day. Ofelia can't run this: it has no last-day or nearest-weekday syntax. vs RunWisp
  • ✗ Dagu Dagu takes 5 fields: minute hour day month weekday. Dagu can't run this: it has no last-day or nearest-weekday syntax. vs RunWisp
  • ↻ PM2 cron_restart 0 0 L * * PM2 cron_restart takes 5 fields, or 6 with seconds first. vs RunWisp
  • ✗ Jobber Jobber doesn't take L for the last day. Jobber can't run this: it has no last-day or nearest-weekday syntax. vs RunWisp
  • ✗ GitHub Actions GitHub Actions takes 5 fields: minute hour day month weekday. GitHub Actions can't run this: it has no last-day or nearest-weekday syntax.
  • ✗ GitLab CI schedule GitLab CI schedule takes 5 fields: minute hour day month weekday. GitLab CI schedule can't run this: it has no last-day or nearest-weekday syntax.
  • ↻ AWS EventBridge Scheduler cron(0 0 L * ? *) AWS EventBridge Scheduler takes cron() with 6 fields, a year last, and ? in one day field.
  • ✗ Google Cloud Scheduler Google Cloud Scheduler takes 5 fields: minute hour day month weekday. Google Cloud Scheduler can't run this: it has no last-day or nearest-weekday syntax.
  • ✗ Jenkins Jenkins takes 5 fields: minute hour day month weekday. Jenkins can't run this: it has no last-day or nearest-weekday syntax.
  • ✓ Spring @Scheduled 0 0 0 L * ?

✓ works as written · ↻ different syntax · ≠ runs at other times · ? not documented · ✗ can't

Schedulers

On the last day of the month, in every scheduler

Works as written in 2 of 17. Times are UTC; the checker above takes any zone.

Runs in 2027
12
Days with a run
12
Longest gap
31 days

Plain cron has no L. The crontab version runs on the 28th to the 31st and lets GNU date check that tomorrow is the 1st.

SchedulerLineNotes
Debian / Ubuntu cron ↻ 0 0 28-31 * * [ "$(date -d '+1 day' +\%d)" = 01 ] && command Debian / Ubuntu cron takes 5 fields: minute hour day month weekday.
cronie ↻ 0 0 28-31 * * [ "$(date -d '+1 day' +\%d)" = 01 ] && command cronie takes 5 fields: minute hour day month weekday.
BusyBox crond ✗ BusyBox crond takes 5 fields: minute hour day month weekday. BusyBox crond can't run this: it has no last-day or nearest-weekday syntax.
systemd timer ↻ OnCalendar=*-*~01 00:00:00 UTC systemd timer uses OnCalendar=, not cron lines.
RunWisp ↻ 0 0 28-31 * * [ "$(date -d '+1 day' +%d)" = 01 ] && command RunWisp takes 5 fields, or 6 with seconds first.
Kubernetes CronJob ✗ Kubernetes CronJob takes 5 fields: minute hour day month weekday. Kubernetes CronJob can't run this: it has no last-day or nearest-weekday syntax.
Ofelia ✗ Ofelia doesn't take L for the last day. Ofelia can't run this: it has no last-day or nearest-weekday syntax.
Dagu ✗ Dagu takes 5 fields: minute hour day month weekday. Dagu can't run this: it has no last-day or nearest-weekday syntax.
PM2 cron_restart ↻ 0 0 L * * PM2 cron_restart takes 5 fields, or 6 with seconds first.
Jobber ✗ Jobber doesn't take L for the last day. Jobber can't run this: it has no last-day or nearest-weekday syntax.
GitHub Actions ✗ GitHub Actions takes 5 fields: minute hour day month weekday. GitHub Actions can't run this: it has no last-day or nearest-weekday syntax.
GitLab CI schedule ✗ GitLab CI schedule takes 5 fields: minute hour day month weekday. GitLab CI schedule can't run this: it has no last-day or nearest-weekday syntax.
AWS EventBridge Scheduler ↻ cron(0 0 L * ? *) AWS EventBridge Scheduler takes cron() with 6 fields, a year last, and ? in one day field.
Google Cloud Scheduler ✗ Google Cloud Scheduler takes 5 fields: minute hour day month weekday. Google Cloud Scheduler can't run this: it has no last-day or nearest-weekday syntax.
Jenkins ✗ Jenkins takes 5 fields: minute hour day month weekday. Jenkins can't run this: it has no last-day or nearest-weekday syntax.
Quartz ✓ 0 0 0 L * ? Works as written.
Spring @Scheduled ✓ 0 0 0 L * ? Works as written.

✓ works as written · ↻ different syntax · ≠ runs at other times · ? not documented · ✗ can't

RunWisp

Cron runs the line. Nobody tells you how it went.

RunWisp is an open-source cron replacement that ships as a single binary. It reads the same cron line and keeps a record of every run: output, exit code, duration.

crontab
# crontab -e  (runs on the server's clock: UTC)
0 0 28-31 * *  [ "$(date -d '+1 day' +\%d)" = 01 ] && /usr/local/bin/job.sh
runwisp.toml
[tasks.job]
cron     = "0 0 28-31 * *"
timezone = "UTC"
run      = "[ \"$(date -d '+1 day' +%d)\" = 01 ] && /usr/local/bin/job.sh"
cronRunWisp
The server was off at run time Skipped. anacron only catches up cron.daily, weekly and monthly. Runs the most recent missed run at start-up (catch_up = 1) and sends a missed-run alert.
The last run is still going Starts another copy on top. Queues it. on_overlap = "queue" is the default.
A run fails Output is mailed if MAILTO and a mail server work. No output, no mail, whatever the exit code. Marked failed and sent to your alert channels. retry_attempts adds retries.

Keep your crontab. sudo runwisp takeover runs it where it is and retires cron, crontab -e keeps working, and runwisp service uninstall puts cron back. It needs Linux with systemd; elsewhere, runwisp import cron converts the file. RunWisp doesn't do L, W or #, and it runs on one machine, not a cluster. Moving from cron →

FAQ

Questions

What does 0 0 0 L * ? mean?
At 00:00 on the last day of the month. In 2027 that's 12 runs on 12 days. Times are in the scheduler's time zone, usually the server's.
How do I run a job on the last day of the month in a crontab?
0 0 28-31 * * [ "$(date -d '+1 day' +\%d)" = 01 ] && command. Debian / Ubuntu cron takes 5 fields: minute hour day month weekday.
How do I run a job on the last day of the month with a systemd timer?
OnCalendar=*-*~01 00:00:00 UTC. systemd timer uses OnCalendar=, not cron lines.
How do I run a job on the last day of the month in a Kubernetes CronJob?
Kubernetes CronJob takes 5 fields: minute hour day month weekday. Kubernetes CronJob can't run this: it has no last-day or nearest-weekday syntax.
How do I run a job on the last day of the month in GitHub Actions?
GitHub Actions takes 5 fields: minute hour day month weekday. GitHub Actions can't run this: it has no last-day or nearest-weekday syntax.
How do I run a job on the last day of the month on AWS EventBridge?
cron(0 0 L * ? *). AWS EventBridge Scheduler takes cron() with 6 fields, a year last, and ? in one day field.
More
Get started
GPL 3.0 · no accounts · free to self-host

Start in 30 seconds. Ship on your terms.

A single Go binary. If it doesn't earn the disk space, rm it. No account, no signup, no catch.

Install in 30 seconds
curl -fsSL https://get.runwisp.com | sh