Job schedules in Obsidian are specified using cron syntax, with some custom extensions to support recurrence. This page provides a reference for writing your own cron expressions, and documents the cron extensions that Obsidian supports.
Cron expressions are written using 5 fields separated by spaces, as indicated below.
.------------------------- minute (0 - 59) | .--------------------- hour (0 - 23) | | .----------------- day of month (1 - 31) | | | .------------- month (1 - 12) | | | | .--------- day of week (0 - 7) (Sunday = 0 or 7) | | | | | .----- year (optional) | | | | | | .- TimeZone ID (optional) * available as of Obsidian 4.2.0 | | | | | | | * * * * * * *
Ordinals indicate specific times, days or months that apply, while an asterisk (*) means there is no restriction on that field. For example, using an asterisk for the month field means the schedule runs during all months, while using "1" would mean it only runs in January. Using 5 asterisks will cause a job to run every minute.
The most basic cron expressions use simple ordinals or an asterisk for each field. As an example, the pattern
30 19 * * 5 means 7:30 PM on all Fridays.
As of Obsidian 3.3.0, multiple Cron patterns may be specified for a single schedule by delimiting them with a semi-colon (e.g.
35 8 * * * *;20 12 * * *;40 16 * * *). This means that the job will fire if it matches any of the supplied patterns.
As of Obsidian 4.2.0, TimeZone ID support was added. This allows for a cron pattern to be associated with a specific TimeZone. The job will fire according to the timing of the TimeZone specified regardless of the default TimeZone of the Obsidian cluster. Supported TimeZone IDs can be found by running TimeZone.getAvailableIDs() in your runtime JVM.
Special Characters and Allowed Values
In addition to ordinals and asterisks, Obsidian supports special characters to support clearer or more complex expressions, as indicated below. These characters allow for ranges, lists and other special handling.
|Field Name||Allowed Ordinal Values||Allowed Special Characters||Required|
|Minute||0-59||* / , -||Yes|
|Hour||0-23||* / , -||Yes|
|Day of Month||1-31||* / , - L W||Yes|
|Month||1-12 or JAN-DEC||* / , -||Yes|
|Day of Week||0-7 or SUN-SAT||* / , - L #||Yes|
|Year||2010-2999||* / , -||No|
Special Character Usage
(run every midnight)
|Asterisks indicate that the expression will match for all values of the field. For example, using an asterisk in the 4th field (month) would indicate every month.|
|Forward slash (/)||
(every even minute)
|Forward slashes are used to describe increments. For example, 0/15 or */15 in the 1st field (minutes) would indicate the 0th minute of the hour and every 15 minutes thereafter. The value before the slash indicates the start value, so 1/2 for the 1st field (minutes) would indicate every odd minute.|
(every 5 minutes, and at 7th minute)
|Commas are used to separate items of a list. For example, using "MON,WED,FRI" in the 5th field (day-of-week) would mean Mondays, Wednesdays and Fridays. Commas can also be used to combine ranges and increments.|
(run from 0th to 15th minute inclusive)
|Hyphens are used to define ranges. For example, 1-3 in the 4th field (month) would indicate January through March inclusive. This could also be written as JAN-MAR.|
(midnight on last Friday of the month)
|"L" stands for last, and can be used in the day-of-week or day-of-month fields. For example, "5L" in the day-of-week field would mean the last Friday of a given month. In the day-of-month field, "L" is used alone to specify the last day of the month.|
(midnight on weekday closest to the 15th of the month)
|"W" is allowed for the day-of-month field. This is used to specify the weekday nearest the given ordinal. For example,specifying "15W" for the day-of-month field, the meaning is "the nearest weekday to the 15th of the month". If the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not jump over the boundary of a month's days. The "W" character can only be specified when the day-of-month is a single day, not a range or list of days.|
(midnight on 2nd Friday of month)
|The hash character is allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify constructs such as "the second Friday" (5#2) of a given month.|
Obsidian supports some shorthand expressions to easily input common expressions. These start with the at sign (@).
|@yearly||0 0 1 1 *||Run once a year, on Jan 1st at midnight.|
|@annually||0 0 1 1 *||Same as @yearly.|
|@monthly||0 0 1 * *||Run once a month, on the 1st at midnight.|
|@weekly||0 0 * * 0||Run once a week, on Sunday at midnight.|
|@daily||0 0 * * *||Run once a day, at midnight.|
|@midnight||0 0 * * *||Same as @daily.|
|@hourly||0 * * * *||Run on the hour, every hour.|
Available as of 3.2.0
In addition to Cron syntax, Obsidian supports special recurrence syntax to allow expression of recurring intervals that can't be defined in a single Cron pattern. For example, if you wanted to run a job every 7 minutes, every 2 weeks or every 5 months, none of these can be expressed in a single Cron pattern.
Obsidian recurrence patterns always start with
@recur and are followed by an interval type. Recurring intervals are calculated from the last execution time, if available. Otherwise, the initial execution will be at the start time of the job schedule. This means that when you schedule a new recurrence, it will execute first when the schedule starts, and then at the interval specified after that.
Note: If an ad hoc job is submitted or a failed job is resubmitted, it will cause the next recurrence interval to be delayed since the next execution time will be based on the last available job.
@recur 7 minutes- every 7 minutes
@recur 7 h- every 7 hours
@recur 3 day- every 3 days
@recur 3 weeks- every 3 weeks
@recur 5 mon- every 5 months
Recurrence Start DateTime
As of 3.4.0, the recurrence pattern may include an optional start datetime. This datetime would be used as a basis for calculating recurrence (if before the effective date of the schedule window), or as the initial recurrence datetime (if after the effective datetime of the schedule window). Without this value, any recurrence pattern without history for the given schedule window will have its first runtime at the effective datetime of the schedule window. When the schedule effective date is greater than the start datetime specified, the first calculated recurrence value that is greater than or equal to the schedule effective datetime will be the first scheduled runtime. See examples below.
This functionality can be used to ensure a job fires on consistent recurrence intervals when migrating between environments, perhaps using the Initializing and Restoring functionality.
DateTime Format is
|Recur Pattern||Effective Date||End Date||First Runtime||Explanation|
||The recurrence start datetime is less than the effective date, but the first calculated recurrence is greater than the schedule effective window.|
||The recurrence start datetime is less than the effective date, but the first (|
||None||The recurrence start datetime is less than the effective date, as are the first (|
||The recurrence start datetime is greater than the effective date and less than the end date. Initial recurrence will start at the specified start datetime.|