# README
The cron
package
The cron
package implements a cron job scheduler with a lot of non-standard extensions.
It allowes to run jobs periodically at fixed times, dates, frequencies and intervals.
Format
The cron expression
is a string with 5, 6 or 7 fields separated by any number of
whitespace like SP
(0x20
) or HT
(0x09
) from the ASCII table. Additionally,
this cron
package implements and supports a lot of Non-Standard Macros
as listed below.
Fields
The standard crontab supports only 5 fields and cannot be scaled to seconds or years. The current implementation completes the fields as following:
- If only 5 fields are present, the
seconds
field with value0
is added to the begin and theyear
field with value*
is added to the end of the fields list. - If only 6 fields are present, the
year
field with value*
is added to the end of the fields list.
Field name | Required | Description | Allowed values | Allowed special characters |
---|---|---|---|---|
seconds | ✕ | Represents seconds. | 0-59 | , - * / . R |
minutes | ✓ | Represents minutes. | 0-59 | , - * / . R |
hours | ✓ | Represents hours. | 0-23 | , - * / . R |
dom | ✓ | Represents days-of-month. | 1-31 | , - * / . R ? L W |
month | ✓ | Represents months. | 1-12 or JAN-DEC | , - * / . R |
dow | ✓ | Represents days-of-week. | 0-7 or SUN-SAT | , - * / . R ? L # |
year | ✕ | Represents years. | 1970-2099 | , - * / . R |
Note: Both,
0
and7
value in thedow
(days-of-week) field is interpreted asSUN
(Sunday).
Note: The names in
month
anddow
(days-of-week) fields and the special charactersR
,L
andW
are case insensitive. For example,FRI
is the same asFri
orfri
.
Special Characters
Special Character | Description |
---|---|
, | Commas are used to separate values in a field. For example, using MON,FRI,SUN in the dow (days-of-week) field means Monday, Friday and Sunday . |
- | Hyphen defines ranges. For example, JAN-MAR in the month field means Januar, Februar and March . The current implementation supports ranges with "range-overflows" for all expression fields excepting the year field. For example, FRI-MON in the dow (days-of-week) field means Friday, Saturday, Sunday and Monday . A mix of names and numeric values in month and dow (days-of-week) fields is supported, too. For example, JAN-MAR is the same as JAN-3 . |
* | Asterisk is used to select all possible values within a field. For example, * in the month field means daily or every day . |
/ | Slash can be used to specify frequencies. For example, */10 in the seconds field means every 10 seconds . And 10/15 in the minutes field means the minutes 10, 25, 40 and 55 . |
. | Dot can be used to specify the current date or time value on the startup. For example, 0 . . * * * * would be updated to 0 9 15 * * * * if the cron is started-up at 09:15. |
? | Question mark is used for leaving either, dom (day-of-month) or dow (day-of-week) blank. For example, 0 0 0 15 * ? * would trigger the cronjob at 15th of every month regardless of what day-of-week it is. |
R | R stands for random . R can be combined with ranges, e.g. 10-30/R in the minutes field. Once generated during parsing, the random number remains constant for current field. If used in the dom (day-of-month) field without ranges, the possible values are limited to the range 1-28 . To be able to use the total range set 1-31/R to the dom (day-of-month) field. |
L | L stands for last . When this character is used in the dom (day-of-month) field, it specifies the last day of the month. For example, 31 January or 29 February in a leap year. In the dow (day-of-week) field, it specifies the last day of the week and simply means the SAT or 6 . When this character is used in the dow (day-of-week) field and is prefixed with a number, it means the last X day of the month . For example, 1L means the last Monday of the month . MONL is the same as 1L . |
W | W stands for weekday (Monday-Friday). W is used to specify the business day nearest the given day in the given month. It never jumps over the boundary of the month's days. For example, if 1W is a Saturday, the cronjob would trigger at Monday, the 3rd. The L and W special characters can also be combined in the dom (day-of-month) field as LW , which means last weekday of the month . |
# | Hash allows to specifying constructs such as the second Friday of a given month. For example, 5#3 in the dow (day-of-week) field means the third Friday of every month . The value before the # has the range 0-7 or SUN-SAT . The value after the # has the range 1-5 . |
Note: Be careful with the use of
?
and*
special characters in thedom
(day-of-month) ordow
(day-of-week) fields.
Note: Avoid cronjobs at
daylight saving times
. Cronjobs can be skiped or repeated depending on whether the time moves back or jumps forward.
Note: It is not allowed to combine the
?
with other values within a field. This special character can only be used exclusively within a field.
Note: It is not allowed to define the
?
special character in both,dom
(days-of-month) anddow
(days-of-week) fields at the same time.
Note: If both, the
dom
(day-of-month) anddow
(day-of-week) fields contain any values excepting the?
, the day is calculated from the best possible value of the both fields.
Non-Standard Macros
Macro | Description | Equivalent expression |
---|---|---|
@yearly | Run once a year at midnight of 1 January. | 0 0 0 1 1 * * |
@annually | The same as @yearly . | 0 0 0 1 1 * * |
@monthly | Run once a month at midnight of the first day of the month. | 0 0 0 1 * * * |
@weekly | Run once a week at midnight on Sunday. | 0 0 0 * * 0 * |
@daily | Run once a day at midnight. | 0 0 0 * * * * |
@midnight | The same as @daily . | 0 0 0 * * * * |
@hourly | Run once an hour at the beginning of the hour. | 0 0 * * * * * |
@minutely | Run once a minute at the beginning of the minute. | 0 * * * * * * |
@every_minute | The same as @minutely . | 0 * * * * * * |
@secondly | Run secondly. | * * * * * * * |
@every_second | The same as @secondly . | * * * * * * * |
@reboot | Run once at startup. | ✕ |
Examples
Expression | Description |
---|---|
0 11 11 11 11 ? * | Run every November 11th at 11:11am. |
59 59 23 31 12 ? * | Run at every turn of the year. |
0 0 0 ? * LW * | Run at every last business day on the month. |
0 0 0 ? * 5L * | Run at every last Friday on the month. |
0 0 0 29 2 ? * | Run every February 29th on every leap year. |
0 0 R * * * * | Run once a day at a random hour. |
0 0 2-6/R * * * * | Run once a day at a random hour between 2:00am and 6:00am. |
Code Example
import "github.com/alex-schneider/cron"
func main() {
ctx := context.Background()
ch, err := cron.NewJobCh(ctx, "@hourly")
if err != nil {
// Handle err
}
myLoop:
for {
select {
case job := <-ch:
switch job.State {
case int(cron.StateFound):
go func() { /* ... */ }() // Trigger some job...
case int(cron.StateNoMatches): // "* * * * * * 2021"
fallthrough
case int(cron.StateOnceExec): // "@reboot"
break myLoop // Handle an end of a job...
}
case <-ctx.Done():
/* ... */
}
}
}