Concept

What does ? mean in cron?

The question mark means "no specific value" and is only valid in Quartz and AWS EventBridge. It's used in either the day-of-month or day-of-week field to indicate "use the other day field." Standard Unix cron does NOT support ?.

Why ? exists

Unix cron has a quirky rule: when both day-of-month and day-of-week are restricted, it fires when EITHER matches (OR logic). This causes endless confusion.

Quartz and AWS sidestep the confusion by requiring one of the two day fields to be ?:

0 0 9 ? * MON-FRI    # Quartz: 9 AM every weekday
                     #    ↑     ↑
                     #    day-of-month = "no specific value"
                     #    day-of-week = MON-FRI

This is unambiguous: we want to fire based on day-of-week, ignore day-of-month.

The rule

In Quartz, you must use ? in exactly one of the day fields. Setting both day fields with concrete values is an error:

0 0 9 15 * MON-FRI    # ERROR — both day fields restricted
0 0 9 ? * MON-FRI     # OK — fires every weekday at 9 AM
0 0 9 15 * ?          # OK — fires on the 15th of every month at 9 AM

This is a feature, not a limitation — the syntax forces you to choose your intent.

AWS EventBridge specifics

AWS uses the same rule, with the added requirement that ALL six fields are present (including the year as the 6th field):

cron(0 9 ? * MON-FRI *)     # Weekdays at 9 AM, any year
cron(0 9 15 * ? *)          # 15th of every month at 9 AM
cron(0 9 ? * MON-FRI 2026)  # Only in 2026

When you'd use ? in day-of-month

Whenever you want the schedule to depend on the day of the week, not the calendar day:

0 9 ? * MON                  # Every Monday at 9 AM
0 0 ? * 2#1                  # First Monday of every month, midnight
                             # (2 = Monday in Quartz, #1 = first occurrence)
0 0 ? * 6L                   # Last Friday of every month at midnight

When you'd use ? in day-of-week

Whenever you want the schedule to depend on the calendar day, regardless of weekday:

0 0 1 * ?                    # 1st of every month at midnight
0 0 L * ?                    # Last day of every month at midnight
0 0 15W * ?                  # Nearest weekday to the 15th

Don't try to use ? in Unix cron

Standard Unix cron (Linux crontab, Kubernetes CronJob, GitHub Actions) does NOT support ?. Trying to use it produces an error or silent failure:

# Unix cron — INVALID
0 9 ? * 1-5

# Unix cron — VALID equivalent (uses * instead)
0 9 * * 1-5

The Unix equivalent works because the wildcard * in day-of-month combined with a restricted day-of-week field gets you "every day that's Mon-Fri" — which is what you want.

Related

Continue reading.