/

Cron: First Monday (Nth Weekday) of the Month

Cron has no native way to express 'the first Monday of the month' or any Nth-weekday-of-month pattern — and the trick you'll see in a lot of blog posts and Stack Overflow answers (something like 0 0 1-7 * 1) is actually wrong, due to how cron's day-of-month and day-of-week fields interact. The correct approach schedules the job weekly and pushes the 'which week' check into the job itself.

Examples & Variations

0 0 * * 1

Every Monday at midnight — building block for 'first Monday'

Try it

0 0 * * 5

Every Friday at midnight — building block for 'last Friday'

Try it

0 9 * * 2

Every Tuesday at 9 AM — building block for 'second Tuesday'

Try it

Common Mistakes

  • Using 0 0 1-7 * 1 expecting it to mean 'the first Monday of the month' — it doesn't. When both day-of-month and day-of-week are restricted (non-*), standard cron treats them as OR, not AND: this expression actually runs on every day 1 through 7 of the month AND on every Monday all month long — a much broader schedule than intended.
  • Not realizing this OR-semantics gotcha applies to any attempt to combine day-of-month and day-of-week restrictions in standard cron — it's one of the most consistently miswritten patterns in cron usage, including in a fair number of published tutorials.
  • Trying to solve 'last Friday of the month' with a fixed day-of-month range (like 24-31) — the last Friday's date shifts between the 24th and 31st depending on the month and year, so no fixed day-of-month range covers it correctly for every month.

Best Practices

  • Schedule the job to run every week on the target weekday (0 0 * * 1 for every Monday), then have the job itself check the date and exit immediately unless it's the intended occurrence (first, second, last, etc.) of that weekday in the current month.
  • For 'last' occurrences (last Friday of the month), check whether adding 7 days to the current date would roll into the next month — if so, the current date is the last occurrence of that weekday.
  • If your platform is Quartz-based (Jenkins, Spring Scheduler) rather than standard cron, use Quartz's native # syntax instead — for example 1#1 means 'the first Monday' directly in a single field, no in-script check required. See the Quartz Scheduler guide for the full day-of-week numbering.

Frequently Asked Questions

Why doesn't 0 0 1-7 * 1 mean 'the first Monday of the month'?
Because standard cron treats day-of-month and day-of-week as an OR condition whenever both are restricted, not an AND. That expression actually fires on every day from the 1st through the 7th (regardless of weekday) plus every Monday of the month (regardless of date) — a much broader schedule than 'just the first Monday'.
What's the actual correct way to run something on the first Monday of the month?
Schedule the job to run every Monday (0 0 * * 1), then add a check inside the script itself: if the day of the month is 7 or less, it's the first occurrence of that weekday in the month — proceed; otherwise, exit without doing anything.
Does any cron-like system support this natively?
Quartz (used by Jenkins, Spring Scheduler, and others) supports a # character specifically for this: 1#1 means 'the first Monday of the month' directly, with no in-script logic needed. Standard 5-field cron has no equivalent.