cronuru
Pattern

Last Day of Month

0 0 28-31 * *
0 0 0 L * ?
0 0 28-31 * * # (with script-level last-day check)
0 0 L * ? *
0 0 0 L * *

Runs at 00:00 on the 28th-31st (the Unix-cron workaround). Quartz, EventBridge, and Spring support `L` for true last-day-of-month.

Use in your stack

# Unix workaround: fire on the 28th-31st, then exit unless today is the last day.
0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom-billing.sh

# On macOS / BSD: use date -v
0 0 28-31 * * [ "$(date -v+1d +\%d)" = "01" ] && /usr/local/bin/eom-billing.sh
{ "cron": "0 0 0 L * ?", "timezone": "UTC" }
apiVersion: batch/v1
kind: CronJob
metadata:
  name: eom-billing
spec:
  # Fires on the 28th-31st; the container script must check whether
  # tomorrow is the 1st before doing any real work.
  schedule: "0 0 28-31 * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: billing
            image: my-image:latest
            command: ["/bin/sh", "-c"]
            args:
            - 'if [ "$(date -d tomorrow +%d)" = "01" ]; then /app/eom-billing.sh; fi'
          restartPolicy: OnFailure
# Native L support — runs on the actual last day of every month
cron(0 0 L * ? *)
@Scheduled(cron = "0 0 0 L * *")   // Spring supports L in day-of-month
public void endOfMonth() { /* ... */ }

Next runs

Pick a timezone to see when this expression fires next.

Next 10 runs
  1. 012026-07-28T00:00:00.000Z
  2. 022026-07-29T00:00:00.000Z
  3. 032026-07-30T00:00:00.000Z
  4. 042026-07-31T00:00:00.000Z
  5. 052026-08-28T00:00:00.000Z
  6. 062026-08-29T00:00:00.000Z
  7. 072026-08-30T00:00:00.000Z
  8. 082026-08-31T00:00:00.000Z
  9. 092026-09-28T00:00:00.000Z
  10. 102026-09-29T00:00:00.000Z

Variations

Common use cases

  • End-of-month billing, ledger close, or financial reporting.
  • Generating reports that need to include the entire month's data.
  • Archiving or rotating data on a calendar-month boundary.
  • Sending end-of-period reminders or notifications.

Gotchas

  • **Standard Unix cron cannot express "last day of month" directly.** The day field is a fixed 1–31, with no awareness of month length. Use a script guard (see Linux example below) or pick a dialect that supports `L`.
  • Quartz and AWS EventBridge support `L` in the day-of-month field — `L` means "the last day of the month" (so 28th in non-leap February, 29th in leap February, 30th or 31st depending on the month).
  • Quartz also supports `LW` — "the last weekday of the month." If the last day falls on a weekend, the job runs on the closest preceding Friday instead.
  • For Kubernetes CronJob (which uses Unix syntax), the standard workaround is `0 0 28-31 * *` with an in-script check that today's date is the last day.

“Last day of the month” is the single biggest reason engineers reach for Quartz or AWS EventBridge over standard Unix cron. The L character makes the schedule trivial; without it, you’re stuck with a multi-day schedule plus a guard inside your script. The shape of the workaround is well-established — but if you’re writing it from scratch, it’s worth knowing whether your target scheduler supports L natively.

Frequently asked questions

Why can't Unix cron express "last day of the month"?
Because the day-of-month field is a fixed 1–31 with no awareness of how many days a given month actually has. There's no syntax for "the last" — only for specific dates. The Unix workaround is to fire on the 28th through 31st, then check inside the script whether tomorrow is the 1st.
What does `L` mean in Quartz or AWS EventBridge?
In the day-of-month field, `L` means "the last day of the month" — automatically 28 in non-leap February, 29 in leap February, 30 in April/June/September/November, 31 otherwise. In the day-of-week field, `L` means "the last day of the week" (Saturday). A number with `L` is the last of that weekday: since Quartz and EventBridge number Sunday as 1, Friday is 6, so `6L` means "the last Friday of the month" (`5L` would be the last Thursday).
How do I run on the last weekday of the month?
In Quartz or AWS EventBridge: `0 0 0 LW * ?`. The `LW` combination means "the last weekday" — if the last day of the month is Saturday or Sunday, the job runs on the closest preceding Friday. Useful for end-of-month business jobs that shouldn't fire on weekends.
What's the script trick for Unix cron?
Schedule for the 28th–31st, then inside the script check if tomorrow is the 1st. On Linux: `[ "$(date -d tomorrow +%d)" = "01" ] && do-the-thing`. On macOS/BSD where `date -d` isn't available: `[ "$(date -v+1d +%d)" = "01" ] && do-the-thing`. The cron fires four times near month-end but the real work only runs once.
Does Kubernetes CronJob support `L`?
No. Kubernetes CronJob uses standard Unix 5-field cron — `L` is a Quartz/EventBridge extension. To run on the last day of the month in K8s, use the schedule `0 0 28-31 * *` and put the last-day check inside the container command.

Browse all cron patterns

Every schedule Cronuru documents, with its expression and code snippets for six dialects.