The cron day of month field: 1 to 31 and missing dates
The day of month field accepts 1 through 31. Because it starts at 1 rather than 0, a step gives odd numbered days, and dates above 28 do not exist in every month.
At a glance
- Range
- 1 to 31.
- Position
- Third of five fields, or fourth of six.
- Field minimum
- 1, not 0. Steps therefore start at day 1.
- Guaranteed dates
- 1 through 28. Every later date is missing from at least one month.
- Missing dates
- The 31st exists in seven months, the 30th in eleven, the 29th in eleven or twelve.
- Interaction
- Combined with the day of week field using OR whenever both are restricted.
In detail
This field is the one where a valid expression most often produces fewer runs than expected. A date that does not exist in a month cannot match, and cron does not defer or roll it forward, so a job pinned to the 31st runs seven times a year and nothing anywhere reports the five missing months.
It is also the only field besides the month field whose minimum is 1 rather than 0, which changes how steps behave. */2 walks 1, 3, 5 and gives odd numbered days, where the same step in the minute field gives even values. Getting even days requires the explicit range 2-30/2.
The step restarts at the beginning of every month rather than continuing across the boundary, so a schedule like */3 is not a genuine three day interval. It gives days 1, 4, 7 and so on up to 28 or 31, and then starts again at the 1st, which produces a one day gap after any month ending on a matched date.
Finally, this field does not stand alone. If the day of week field is also restricted, cron matches a date when either field matches, not both. Leaving the day of week field as an asterisk is what keeps a day of month restriction meaning what it appears to mean.
Examples
0 0 1 * *The 1st exists in every month, so twelve runs a year.
0 0 31 * *Seven runs a year. February, April, June, September and November are skipped.
0 0 2-30/2 * *A plain */2 would give odd days, because the field starts at 1.
Things that catch people out
- Days 29, 30 and 31 are not present in every month, and a missed date is simply never run.
- */2 gives odd days here, which surprises anyone used to the minute field.
- Restricting this field and the day of week field at the same time switches the two to OR, which almost always produces more runs than intended.
Try it: Cron Expression Parser
Paste any five or six field expression to get a plain English description, a per field breakdown and the next run times in your local time.
Cron Expression Parser
LOCAL · Browser-OnlyParse cron expressions and see the next scheduled run times
Supports 5-field (minute hour day month weekday), 6-field (with seconds), named values (JAN, MON), and @macros (@daily, @hourly, ...)
Use the dropdowns below to build your cron expression visually, or type a custom value in each field.
Human-Readable Description
Every 5 minutes
Field Breakdown
| Field | Allowed | Value | Meaning |
|---|---|---|---|
| Minute | 0-59 | */5 | every 5 minute(s) |
| Hour | 0-23 | * | every hour |
| Day of Month | 1-31 | * | every day of month |
| Month | 1-12 | * | every month |
| Day of Week | 0-7 | * | every day of week |
Related cron expressions
All cron expressions →Cron day of month and day of week: the OR rule
When both date fields are restricted, cron fires if either matches, not both. This turns narrowing expressions into much wider ones without any error.
Cron on the 31st: 0 0 31 * * only fires seven times a year
0 0 31 * * runs only in months that have 31 days, so it fires seven times a year, not twelve. The same trap hits day 30 and day 29.
Cron every other day: 0 0 */2 * * and the month reset
0 0 */2 * * runs on odd numbered days, 16 times in a 31 day month. The step resets each month, so the 31st and the 1st are consecutive runs.
The cron month field: 1 to 12 with JAN to DEC aliases
The month field runs 1 to 12 and also accepts the three letter names JAN through DEC, case insensitively, including inside ranges and steps.
The cron day of week field: 0 to 7 with Sunday at both ends
The day of week field runs 0 to 7 with Sunday as both 0 and 7, and accepts SUN through SAT. Restricting it changes how the day of month field behaves.
The cron seconds field: the optional sixth position
A six field expression puts seconds first and shifts everything right. The system crontab has no seconds field, so six fields there means a broken job.
Tools for this
- Cron Expression Parser Free online cron expression parser - parse cron expressions and see the next scheduled run times
- Crontab Generator Free online crontab generator - build cron expressions visually with an intuitive interface