Quartz.NET "?" vs "*"
A cron expression that would be perfectly valid in Hangfire or plain Unix cron throws Support for specifying both a day-of-week AND a day-of-month parameter is not implemented in Quartz.NET, for an expression that doesn't look like it's specifying both of anything. The rule is narrower and stricter than it first appears.
// the actual rule
0 0 12 * * ?Valid. Day-of-month is *, day-of-week is ? — fires every day at noon.0 0 6 ? * MONValid. Day-of-month is ?, day-of-week is MON — fires every Monday at 6 AM.0 0 12 * * *Invalid. Neither field is ? — throws the "not implemented" error, even though both fields are just wildcards.0 0 6 15 * MONInvalid, for a different reason: this looks like it's asking for "the 15th, and also every Monday," which cron's AND/OR semantics don't actually resolve the way most people expect even in dialects that allow it. Quartz.NET refuses to guess and requires you to pick one field to leave unconstrained.*, the way they were in the original. That translation is invalid; one of the two has to become ?.// why the restriction exists at all
Standard cron resolves day-of-month and day-of-week with OR logic when both are constrained to specific values — "the 15th, OR any Friday" — which is rarely what anyone actually wants and is a well-documented source of schedules that fire far more often than intended. Quartz.NET sidesteps the ambiguity entirely by making it a parse error instead of a silent surprise: you're forced to explicitly say which of the two fields you're not using, via ?, rather than have the parser guess at AND-vs-OR semantics on your behalf.
// build it without guessing
The Cron Builder & Explainer generates valid Quartz.NET expressions field-by-field, so the ? placement is handled automatically instead of being something to remember while translating between dialects.
// frequently asked questions
Why does Quartz.NET say day-of-week and day-of-month can't both be set?
Because exactly one of the two fields must be ?. It doesn't matter what the other field contains — *, a specific value, a list, a range — as long as one is ?, the expression is valid. The error only fires when neither field is ?, even if both are just wildcards.
Why does 0 0 12 * * * fail in Quartz.NET when it looks like a valid schedule?
Neither the day-of-month nor day-of-week field is ? — both are *, which Quartz.NET still rejects. Standard cron and Hangfire allow this, but Quartz.NET requires you to explicitly mark one of the two fields as unconstrained with ? rather than leaving both as wildcards.
Why does the ? character exist in Quartz.NET at all?
Standard cron resolves day-of-month and day-of-week with OR logic when both are constrained to specific values — "the 15th, OR any Friday" — which is rarely what anyone actually wants. Quartz.NET sidesteps the ambiguity by making it a parse error instead of a silent surprise, forcing you to say explicitly which field you're not using.
Why does translating a Hangfire cron expression to Quartz.NET break it?
The most common trigger for this error isn't a deliberate attempt to combine both fields — it's adding a leading seconds field to a 5-field Hangfire/Unix expression and leaving both day fields as *, the way they were in the original. That translation is invalid in Quartz.NET; one of the two has to become ?.
Quartz.NET expressions have both a day-of-month field and a day-of-week field, and the rule is exact: exactly one of the two must be
?. It doesn't matter what the other field contains —*, a specific value, a list, a range,L,#— as long as one field is?, the expression is valid. The error only fires when neither field is?.