How to use it
- Paste a cron expression. The dialect is detected from the field count.
- Read the plain-English description and the next eight run times.
- The status bar warns you about the day-field trap described below.
The five fields
┌───────────── minute (0-59)
│ ┌─────────── hour (0-23)
│ │ ┌───────── day of month (1-31)
│ │ │ ┌─────── month (1-12 or JAN-DEC)
│ │ │ │ ┌───── day of week (0-6 or SUN-SAT)
│ │ │ │ │
* * * * *
Quartz and Hangfire prepend a seconds field, so 0 30 9 * * MON-FRI means half past nine on weekdays, not "every 30 seconds in September". Misreading a six-field expression as five-field is a common and expensive mistake, which is why this parser reports which dialect it detected.
Four operators appear in every field: * for every value, , for a list, - for a range, and / for a step. 0 9-17/2 * * 1-5 is every two hours between 09:00 and 17:00, Monday to Friday.
The day-field trap
This is the one genuine surprise in cron, and it catches experienced people.
Day-of-month and day-of-week are joined with OR, not AND — but only when both are restricted. If one of them is *, the fields behave as you expect. If both name specific values, the job runs whenever either matches.
So 0 0 1 * MON does not mean "the first of the month, if it is a Monday". It means "every 1st of the month, and also every Monday". A job you thought ran twelve times a year runs about sixty-four.
This is behaviour inherited from the original Vixie cron and deliberately preserved by almost every implementation for compatibility. There is no operator to request AND. If you need "the first Monday of the month", you either use a Quartz extension (#) or check the date inside the job itself.
Time zones and daylight saving
The next-run times here are in your browser's zone. Your scheduler is probably in a different one, and that gap is where cron bugs come from.
Daylight saving makes it worse. When clocks jump forward, a job scheduled for 02:30 in an affected zone has no 02:30 to run at — most implementations skip it. When clocks go back, 02:30 happens twice, and some implementations run the job twice. Neither behaviour is standardised.
The reliable answer is to run schedulers in UTC and handle local presentation in the application. If a job genuinely must fire at local 09:00 year-round, use a scheduler with explicit time-zone support (Quartz.NET has it) rather than hoping the system zone does the right thing.
Reading the next runs
Listing actual future times is the fastest way to check an expression, because a description can be right while your intent was wrong. 0 0 * * 0 is correctly described as "at 00:00 on Sunday" — but if you wanted Monday, the list of dates makes that obvious in a way the sentence does not.
The parser searches forward up to four years. If nothing comes back, the expression can never match — 0 0 30 2 *, the 30th of February, is the classic example.