Quartz Scheduler Cron Guide
Quartz is the most widely used job scheduling library in the Java ecosystem, and its CronExpression class defines a cron dialect that's become influential enough that AWS EventBridge and Spring both adopted variations of it. Quartz cron is more expressive than standard cron, at the cost of a stricter, less forgiving syntax.
Syntax Notes
6 required fields plus an optional 7th: seconds, minutes, hours, day-of-month, month, day-of-week, year (optional). Exactly one of day-of-month/day-of-week must be ? — both can't be * simultaneously, the same constraint AWS EventBridge inherited from Quartz.
Examples
0 30 8 * * ?0 0 0 L * ?0 0 12 ? * 6#1CronTrigger trigger = TriggerBuilder.newTrigger()
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 2 * * ?"))
.build();Gotchas
- Quartz throws a ParseException at trigger-creation time (not silently) if both day-of-month and day-of-week are * — you must set one of them to ? — this is a frequent first-time error for anyone used to standard cron's OR semantics.
- The L (last) and W (nearest weekday) characters can be combined (LW means "last weekday of the month") but have specific restrictions — L can't be used with a list or range of values in the same field, which throws a runtime error if attempted.
- The # character (nth weekday, e.g. 6#3 for the third Friday) only accepts values 1–5, and there's no way to express "last occurrence of weekday X" other than combining it with L in the day-of-month field in specific ways — the syntax here is genuinely more complex than the L/W characters alone suggest.
Best Practices
- Always set day-of-month or day-of-week to ? (never both to *), and treat that as a required first check whenever a Quartz expression fails to parse.
- Use Quartz's own CronExpression.isValidExpression() (or an equivalent validator) at application startup or in tests, rather than discovering a malformed expression when the trigger fires the first time in production.
- Keep a comment next to any expression using L, W, or # explaining the intended date in plain English — these characters are powerful but not immediately readable at a glance.
Frequently Asked Questions
- What does the ? character mean in Quartz cron?
- It means "no specific value" and is required in either the day-of-month or day-of-week field whenever the other field has a specific value — it exists specifically to avoid the ambiguous OR-logic that standard cron uses when both fields are restricted.
- Can I use Quartz cron syntax in a Linux crontab?
- No — the seventh (year) field, the ? character, and L/W/# are all Quartz-specific extensions that standard Vixie/POSIX cron doesn't understand. Quartz expressions need to be translated to standard syntax (dropping unsupported characters) to run on Linux cron.
- Is the year field required?
- No, it's optional — if omitted, Quartz treats the year as unrestricted (matches any year), which is the correct default for the overwhelming majority of recurring schedules.
Related Tools
Platform Guides
Cron syntax for Linux, Kubernetes, AWS, and more
Jenkins Cron Guide
How to schedule Jenkins builds with cron syntax: the Build periodically trigger, the H (hash) character for load distribution, and common patterns.
node-cron Guide
How to schedule recurring tasks in Node.js with the node-cron package: standard cron syntax, timezone options, and common patterns.