Skip to content

Cron on the First Monday of the Month

The first Monday is MON#1 in Quartz, Spring and AWS. Linux cron has no #, and the obvious 1-7 plus Monday runs on 10 or 11 days a month.

second · minute · hour · day · month · weekday · year (optional)

Build it with controlsCustom

This expression is more detailed than these choices. Edit it in the box above, or pick one to start a new schedule.

In plain English

At 9:00 AM on the first Monday of the month.

Tap a field to see what it means.

A week1 run
Mon1Tue–Wed–Thu–Fri–Sat–Sun–
Next run
—
Usually every
—
Time zone
Yours
Convert to another schedulerQuartz, Spring, AWS, GitHub Actions, Kubernetes
The same schedule in every dialect
Standard cronStandard cron has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.
Quartz0 0 9 ? * MON#1current
Spring0 0 9 * * MON#1
AWS EventBridgecron(0 9 ? * 2#1 *)
GitHub ActionsGitHub Actions has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.
KubernetesKubernetes has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.
About QuartzTime zone, day numbering, daylight saving
  • Six or seven fields: seconds first, then minute, hour, day of month, month, day of week and an optional year.
  • Day of week is 1–7 with Sunday as 1, or SUN–SAT. Write MON-FRI rather than numbers.
  • One of the two day fields must be ?. L (last), W (nearest weekday) and # (nth weekday) are allowed.
  • Quartz doesn’t document what happens in a skipped or repeated hour; the runs here assume skipped and once.

Sources: Quartz CronExpression.

How this works: Method, 10 sources, Checked against 2 worked examples,

How this works

Method

Quartz, Spring and AWS have #: MON#1 (or 2#1 in Quartz, where Monday is 2) means the first Monday of the month. 0 0 9 ? * MON#1 runs at 9:00 AM on the first Monday, once a month; MON#2 would be the second. Full method

How it’s tested

2 worked examples for this page are checked by automated tests before every release: given the inputs, the tool must show the expected answer.

Changes

  • First version: plain English and the next runs for six schedulers, a builder, conversion between them, and 20 pages for common schedules.

How we make toolsReport a mistake

Worked example: 0 0 9 ? * MON#1

Say the clock reads Monday 4 January 2027, 10:00 AM UTC. 0 0 9 ? * MON#1 means “at 9:00 AM on the first Monday of the month”, so the next five runs are Monday 1 February 2027, 9:00 AM, Monday 1 March 2027, 9:00 AM, Monday 5 April 2027, 9:00 AM, Monday 3 May 2027, 9:00 AM and Monday 7 June 2027, 9:00 AM.

The nth weekday with #

Quartz, Spring and AWS have #: MON#1 (or 2#1 in Quartz, where Monday is 2) means the first Monday of the month. 0 0 9 ? * MON#1 runs at 9:00 AM on the first Monday, once a month; MON#2 would be the second.

Linux cron has no #, and the obvious attempt, 0 9 1-7 * 1, is a classic trap. When both day fields are set, Vixie cron and cronie run on days that match either one, so that line runs on the 1st to the 7th and on every Monday: 10 or 11 days a month.

The fix is to keep only one day field in cron and test the other in the command: run on days 1 to 7 and check that today is a Monday. In a crontab line, % must be written \%.

0 9 1-7 * * [ "$(date +\%u)" = 1 ] && /path/job.sh

Pitfalls

  • 0 9 1-7 * 1 runs on days 1 to 7 and every Monday (either field), not just the first Monday.
  • Quartz and AWS count Monday as 2, so their 1#1 is the first Sunday. MON#1 is unambiguous.
  • AWS and Quartz allow only one # value in the field: “first and third Monday” needs two schedules.
  • Quartz: 6#3 in the day-of-week field is the third Friday of the month, and 2#1 the first Monday; with #5, months without a fifth such day are skipped. Source: Quartz CronExpression.
  • AWS: 3#2 is the second Tuesday of the month, and only one # expression is allowed in the day-of-week field. Source: Amazon EventBridge Scheduler: schedule types.

“First Monday of the Month” in every scheduler

The same schedule written for each scheduler, converted and checked by this tool. A dash means that scheduler can’t express it in one expression; the note says why.

The same schedule written for each scheduler, converted and checked by this tool. A dash means that scheduler can’t express it in one expression; the note says why.
SchedulerExpressionNote
Standard Unix cron (Vixie cron, cronie)—Standard cron has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.
Quartz Scheduler (Java)0 0 9 ? * MON#1
Spring Framework @Scheduled0 0 9 * * MON#1
Amazon EventBridge cron()cron(0 9 ? * 2#1 *)
GitHub Actions schedule—GitHub Actions has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.
Kubernetes CronJob—Kubernetes has no L, W or # (last day, nearest weekday, nth weekday). A common workaround is to run on the candidate days and test the date in the command.

Frequently Asked Questions

Why does 0 9 1-7 * 1 run on more than the first Monday?

Because when day of month and day of week are both restricted, standard cron runs on days that match either: every day from the 1st to the 7th, plus every Monday.

What is the first Monday of the month in Spring?

0 0 9 * * MON#1. Spring numbers days like cron (Monday is 1), so 1#1 also works there, unlike in Quartz.

How do I do the last Friday of the month?

Use L after the day: 6L in Quartz and AWS (Friday is 6 there), 5L or FRIL in Spring.