Cron special characters: L, W, # and ? explained
Standard cron has four symbols. Quartz-style cron adds L, W, # and ? — the keys to schedules like “last day of the month” and “the first Monday” that plain cron can't express.
Standard cron gives you four symbols — *, ,, - and / — covered in the syntax guide. They handle almost everything, but not "the last day of the month" or "the first Monday". For those, some schedulers add four more characters: L, W, # and ?. Here's what each does.
These are extensions, not standard Unix cron. They come from the Quartz scheduler and appear in Quartz, Spring's
@Scheduled, AWS EventBridge and others. Plain Vixie cron (the/etc/crontabon your Linux box) does not understand them.
? — no specific value
? means "no specific value" and is only valid in the day-of-month and day-of-week fields. Because those two fields interact, schedulers like Quartz and AWS make you put ? in one of them to say "I'm not specifying this one — use the other". For example, "9 AM every weekday" in Quartz is:
0 0 9 ? * MON-FRI
The ? in day-of-month says "the weekday field is in charge here".
L — last
L means "last", and its meaning depends on the field:
- In day-of-month,
Lis the last day of the month — the 28th, 30th or 31st as appropriate. So0 0 L * ?runs at midnight on the last day of every month. L-3means the third-from-last day of the month.- In day-of-week,
Lmeans the last day (Saturday), and5Lmeans the last Friday of the month.
This solves a genuinely common need — "run on the last day of the month" — that standard cron simply cannot express.
W — nearest weekday
W means "the nearest weekday (Mon–Fri) to a given day". 15W in the day-of-month field runs on the weekday closest to the 15th: if the 15th is a Saturday, it runs on Friday the 14th; if it's a Sunday, on Monday the 16th. LW combines the two — the last weekday of the month. Handy for "pay on the nearest business day".
# — the nth weekday of the month
# picks the nth occurrence of a weekday. In the day-of-week field, dayOfWeek#n means "the nth such day". So 6#3 is the third Friday of the month (with Sunday = 1, Friday = 6 in Quartz numbering), and 2#1 is the first Monday. This is how you express "the first Monday of every month" — something plain cron gets wrong because it ORs the two day fields.
Support varies by scheduler
| Character | Unix cron | Quartz | Spring @Scheduled |
AWS EventBridge |
|---|---|---|---|---|
? |
No | Yes | Yes | Yes |
L |
No | Yes | Yes | Partly |
W |
No | Yes | Yes | Partly |
# |
No | Yes | Yes | Yes |
Numbering also differs — Quartz and AWS use day-of-week 1–7 with Sunday = 1, whereas Unix cron uses 0–6 with Sunday = 0. Always confirm against your target system's docs, and see the cross-system guide for the wider picture.
The takeaway
If you only run classic Linux cron, stick to the four standard symbols and handle "last day" or "first Monday" logic inside your script. If your scheduler is Quartz, Spring or AWS, L, W, # and ? let you express those schedules directly — just remember they're a different dialect from the crontab on your server.