Pattern
Croner is compliant with the Open Cron Pattern Specification (OCPS) versions 1.0 through 1.4, with one documented deviation in the recommended DST handling (see below). The expressions are based on Vixie Cron with powerful extensions:
// ┌──────────────── (optional) second (0 - 59)
// │ ┌────────────── minute (0 - 59)
// │ │ ┌──────────── hour (0 - 23)
// │ │ │ ┌────────── day of month (1 - 31)
// │ │ │ │ ┌──────── month (1 - 12, JAN-DEC)
// │ │ │ │ │ ┌────── day of week (0 - 6, SUN-Mon)
// │ │ │ │ │ │ (0 to 6 are Sunday to Saturday; 7 is Sunday, the same as 0)
// │ │ │ │ │ │
// * * * * * *
-
OCPS 1.2: Optional second and year fields for enhanced precision:
- 6-field format:
SECOND MINUTE HOUR DAY-OF-MONTH MONTH DAY-OF-WEEK - 7-field format:
SECOND MINUTE HOUR DAY-OF-MONTH MONTH DAY-OF-WEEK YEAR - Supported year range: 1-9999
- 6-field format:
-
OCPS 1.3: Advanced calendar modifiers:
- L: Last day of month or last occurrence of a weekday.
Lin day-of-month = last day of month;5#LorFRI#L= last Friday of the month. - W: Nearest weekday.
15Wtriggers on the weekday closest to the 15th (moves to Friday if 15th is Saturday, Monday if 15th is Sunday). Won't cross month boundaries. - #: Nth occurrence of a weekday.
5#2= second Friday;MON#1= first Monday of the month.
- L: Last day of month or last occurrence of a weekday.
-
OCPS 1.4: Enhanced logical control:
- +: Explicit AND logic modifier. Prefix the day-of-week field with
+to require both day-of-month AND day-of-week to match. Example:0 12 1 * +MONonly triggers when the 1st is also a Monday. - ?: Wildcard alias (behaves identically to
*). Non-portable: Its use is discouraged in patterns intended for cross-system use. Supported in all fields for compatibility, but primarily meaningful in day-of-month and day-of-week fields. - DST handling, the same as croner-rust and Vixie cron, which deviates from OCPS 1.4 §4.3.1 (see below):
- Fixed-time jobs, with a single value in each of seconds, minutes and hours (e.g.
0 30 2 * * *): A time that occurs twice (DST fall back) runs once, at the first occurrence. A time that doesn't exist (DST spring forward) runs at the first valid time after the gap, on the same day. - Interval jobs, with a wildcard, step, range or list in seconds, minutes or hours (e.g.
*/5 * * * *or0 30 1,2 * * *): A time that occurs twice runs on both occurrences, so the job keeps running through the repeated hour. A time that doesn't exist is skipped. nextRun(),nextRuns(),previousRuns()andenumerate()move in real time. They never return a time they have passed, and cover the first pass through a repeated hour before the second.
- Fixed-time jobs, with a single value in each of seconds, minutes and hours (e.g.
- +: Explicit AND logic modifier. Prefix the day-of-week field with
Deviation from OCPS 1.4: OCPS 1.4 §4.3.1 recommends that every job skips times in a DST gap, and runs only once when a time occurs twice. The same section asks implementations to align with Vixie cron, which runs interval jobs on both occurrences and runs fixed-time jobs after a gap. Croner follows Vixie cron, as croner-rust does, so that both libraries schedule the same.
-
Croner allows you to pass a JavaScript Date object or an ISO 8601 formatted string as a pattern. The scheduled function will trigger at the specified date/time and only once. If you use a timezone different from the local timezone, you should pass the ISO 8601 local time in the target location and specify the timezone using the options (2nd parameter).
-
By default, Croner uses OR logic for day-of-month and day-of-week (OCPS 1.0 compliant). Example:
0 20 1 * MONtriggers on the 1st of the month OR on Mondays. Use the+modifier (0 20 1 * +MON) or{ domAndDow: true }for AND logic (OCPS 1.4 compliant). For more information, see issue #53.
| Field | Required | Allowed values | Allowed special characters | Remarks |
|---|---|---|---|---|
| Seconds | Optional | 0-59 | * , - / ? | OCPS 1.2: Optional, defaults to 0 |
| Minutes | Yes | 0-59 | * , - / ? | |
| Hours | Yes | 0-23 | * , - / ? | |
| Day of Month | Yes | 1-31 | * , - / ? L W | L = last day, W = nearest weekday |
| Month | Yes | 1-12 or JAN-DEC | * , - / ? | |
| Day of Week | Yes | 0-7 or SUN-MON | * , - / ? L # + | 0 and 7 = Sunday (standard mode) 1-7 = Sunday-Saturday (Quartz mode with alternativeWeekdays: true)# = nth occurrence (e.g. MON#2) + = AND logic modifier (OCPS 1.4) |
| Year | Optional | 1-9999 | * , - / | OCPS 1.2: Optional, defaults to * |
Weekday and month names are case-insensitive. Both
MONandmonwork. When usingLin the Day of Week field with a range, it affects all specified weekdays. For example,5-6#Lmeans the last Friday and Saturday in the month. The#character specifies the "nth" weekday of the month. For example,5#2= second Friday,MON#1= first Monday. TheWcharacter operates within the current month and won't cross month boundaries. If the 1st is a Saturday,1Wmatches Monday the 3rd. The+modifier (OCPS 1.4) enforces AND logic:0 12 1 * +MONonly runs when the 1st is also a Monday. Quartz mode: EnablealternativeWeekdays: trueto use Quartz-style weekday numbering (1=Sunday, 2=Monday, ..., 7=Saturday) instead of the standard format (0=Sunday, 1=Monday, ..., 6=Saturday). This is useful for compatibility with Quartz cron expressions.
OCPS 1.1: Predefined schedule nicknames are supported:
| Nickname | Description |
|---|---|
| @yearly / @annually | Run once a year, i.e. "0 0 1 1 *". |
| @monthly | Run once a month, i.e. "0 0 1 * *". |
| @weekly | Run once a week, i.e. "0 0 * * 0". |
| @daily / @midnight | Run once a day, i.e. "0 0 * * *". |
| @hourly | Run once an hour, i.e. "0 * * * *". |
| @reboot | Recognized but not supported. Throws an error as Croner cannot detect system reboot events. |