This commit is contained in:
gorhill 2013-08-31 08:23:51 -04:00
parent e41acb76c8
commit 8af06bafc9
2 changed files with 132 additions and 132 deletions

View File

@ -83,10 +83,10 @@ Assuming `time.Now()` is "2013-08-29 09:28:00", then `nextTime` will be "2016-02
You can keep the returned Expression pointer around if you want to reuse it: You can keep the returned Expression pointer around if you want to reuse it:
cronexpr := cronexpression.Parse("0 0 29 2 *") expr := cronexpression.Parse("0 0 29 2 *")
nextTime := cronexpr.Next(time.Now()) nextTime := expr.Next(time.Now())
... ...
nextTime := cronexpr.Next(nextTime) nextTime := expr.Next(nextTime)
Use `time.IsZero()` to find out whether a valid time was returned. For example, Use `time.IsZero()` to find out whether a valid time was returned. For example,

View File

@ -98,15 +98,15 @@ func Parse(cronLine string) *Expression {
/******************************************************************************/ /******************************************************************************/
// Given a time stamp `fromTime`, return the closest following time stamp which // Given a time stamp `fromTime`, return the closest following time stamp which
// matches the cron expression `cronexpr`. The `time.Location` of the returned // matches the cron expression `expr`. The `time.Location` of the returned
// time stamp is the same as `fromTime`. // time stamp is the same as `fromTime`.
func (cronexpr *Expression) Next(fromTime time.Time) time.Time { func (expr *Expression) Next(fromTime time.Time) time.Time {
// Special case // Special case
if fromTime.IsZero() { if fromTime.IsZero() {
return fromTime return fromTime
} }
// Since cronexpr.nextSecond()-cronexpr.nextMonth() expects that the // Since expr.nextSecond()-expr.nextMonth() expects that the
// supplied time stamp is a perfect match to the underlying cron // supplied time stamp is a perfect match to the underlying cron
// expression, and since this function is an entry point where `fromTime` // expression, and since this function is an entry point where `fromTime`
// does not necessarily matches the underlying cron expression, // does not necessarily matches the underlying cron expression,
@ -118,80 +118,80 @@ func (cronexpr *Expression) Next(fromTime time.Time) time.Time {
// year // year
v := fromTime.Year() v := fromTime.Year()
i := sort.SearchInts(cronexpr.yearList, v) i := sort.SearchInts(expr.yearList, v)
if i == len(cronexpr.yearList) { if i == len(expr.yearList) {
return time.Time{} return time.Time{}
} }
if v != cronexpr.yearList[i] { if v != expr.yearList[i] {
return cronexpr.nextYear(fromTime) return expr.nextYear(fromTime)
} }
// month // month
v = int(fromTime.Month()) v = int(fromTime.Month())
i = sort.SearchInts(cronexpr.monthList, v) i = sort.SearchInts(expr.monthList, v)
if i == len(cronexpr.monthList) { if i == len(expr.monthList) {
return cronexpr.nextYear(fromTime) return expr.nextYear(fromTime)
} }
if v != cronexpr.monthList[i] { if v != expr.monthList[i] {
return cronexpr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
cronexpr.actualDaysOfMonthList = cronexpr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month())) expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month()))
if len(cronexpr.actualDaysOfMonthList) == 0 { if len(expr.actualDaysOfMonthList) == 0 {
return cronexpr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
// day of month // day of month
v = fromTime.Day() v = fromTime.Day()
i = sort.SearchInts(cronexpr.actualDaysOfMonthList, v) i = sort.SearchInts(expr.actualDaysOfMonthList, v)
if i == len(cronexpr.actualDaysOfMonthList) { if i == len(expr.actualDaysOfMonthList) {
return cronexpr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
if v != cronexpr.actualDaysOfMonthList[i] { if v != expr.actualDaysOfMonthList[i] {
return cronexpr.nextDayOfMonth(fromTime) return expr.nextDayOfMonth(fromTime)
} }
// hour // hour
v = fromTime.Hour() v = fromTime.Hour()
i = sort.SearchInts(cronexpr.hourList, v) i = sort.SearchInts(expr.hourList, v)
if i == len(cronexpr.hourList) { if i == len(expr.hourList) {
return cronexpr.nextDayOfMonth(fromTime) return expr.nextDayOfMonth(fromTime)
} }
if v != cronexpr.hourList[i] { if v != expr.hourList[i] {
return cronexpr.nextHour(fromTime) return expr.nextHour(fromTime)
} }
// minute // minute
v = fromTime.Minute() v = fromTime.Minute()
i = sort.SearchInts(cronexpr.minuteList, v) i = sort.SearchInts(expr.minuteList, v)
if i == len(cronexpr.minuteList) { if i == len(expr.minuteList) {
return cronexpr.nextHour(fromTime) return expr.nextHour(fromTime)
} }
if v != cronexpr.minuteList[i] { if v != expr.minuteList[i] {
return cronexpr.nextMinute(fromTime) return expr.nextMinute(fromTime)
} }
// second // second
v = fromTime.Second() v = fromTime.Second()
i = sort.SearchInts(cronexpr.secondList, v) i = sort.SearchInts(expr.secondList, v)
if i == len(cronexpr.secondList) { if i == len(expr.secondList) {
return cronexpr.nextMinute(fromTime) return expr.nextMinute(fromTime)
} }
// If we reach this point, there is nothing better to do // If we reach this point, there is nothing better to do
// than to move to the next second // than to move to the next second
return cronexpr.nextSecond(fromTime) return expr.nextSecond(fromTime)
} }
/******************************************************************************/ /******************************************************************************/
// Given a time stamp `fromTime`, return a slice of `n` closest following time // Given a time stamp `fromTime`, return a slice of `n` closest following time
// stamps which match the cron expression `cronexpr`. The time stamps in the // stamps which match the cron expression `expr`. The time stamps in the
// returned slice are in chronological ascending order. The `time.Location` of // returned slice are in chronological ascending order. The `time.Location` of
// the returned time stamps is the same as `fromTime`. // the returned time stamps is the same as `fromTime`.
func (cronexpr *Expression) NextN(fromTime time.Time, n int) []time.Time { func (expr *Expression) NextN(fromTime time.Time, n int) []time.Time {
if n <= 0 { if n <= 0 {
panic("Expression.NextN(): invalid count") panic("Expression.NextN(): invalid count")
} }
nextTimes := make([]time.Time, 0) nextTimes := make([]time.Time, 0)
fromTime = cronexpr.Next(fromTime) fromTime = expr.Next(fromTime)
for { for {
if fromTime.IsZero() { if fromTime.IsZero() {
break break
@ -201,81 +201,81 @@ func (cronexpr *Expression) NextN(fromTime time.Time, n int) []time.Time {
if n == 0 { if n == 0 {
break break
} }
fromTime = cronexpr.nextSecond(fromTime) fromTime = expr.nextSecond(fromTime)
} }
return nextTimes return nextTimes
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextYear(t time.Time) time.Time { func (expr *Expression) nextYear(t time.Time) time.Time {
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate year // candidate year
i := sort.SearchInts(cronexpr.yearList, t.Year()+1) i := sort.SearchInts(expr.yearList, t.Year()+1)
if i == len(cronexpr.yearList) { if i == len(expr.yearList) {
return time.Time{} return time.Time{}
} }
// Year changed, need to recalculate actual days of month // Year changed, need to recalculate actual days of month
cronexpr.actualDaysOfMonthList = cronexpr.calculateActualDaysOfMonth(cronexpr.yearList[i], cronexpr.monthList[0]) expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.yearList[i], expr.monthList[0])
if len(cronexpr.actualDaysOfMonthList) == 0 { if len(expr.actualDaysOfMonthList) == 0 {
return cronexpr.nextMonth(time.Date( return expr.nextMonth(time.Date(
cronexpr.yearList[i], expr.yearList[i],
time.Month(cronexpr.monthList[0]), time.Month(expr.monthList[0]),
1, 1,
cronexpr.hourList[0], expr.hourList[0],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
time.Local)) time.Local))
} }
return time.Date( return time.Date(
cronexpr.yearList[i], expr.yearList[i],
time.Month(cronexpr.monthList[0]), time.Month(expr.monthList[0]),
cronexpr.actualDaysOfMonthList[0], expr.actualDaysOfMonthList[0],
cronexpr.hourList[0], expr.hourList[0],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
time.Local) time.Local)
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextMonth(t time.Time) time.Time { func (expr *Expression) nextMonth(t time.Time) time.Time {
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate month // candidate month
i := sort.SearchInts(cronexpr.monthList, int(t.Month())+1) i := sort.SearchInts(expr.monthList, int(t.Month())+1)
if i == len(cronexpr.monthList) { if i == len(expr.monthList) {
return cronexpr.nextYear(t) return expr.nextYear(t)
} }
// Month changed, need to recalculate actual days of month // Month changed, need to recalculate actual days of month
cronexpr.actualDaysOfMonthList = cronexpr.calculateActualDaysOfMonth(t.Year(), cronexpr.monthList[i]) expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.monthList[i])
if len(cronexpr.actualDaysOfMonthList) == 0 { if len(expr.actualDaysOfMonthList) == 0 {
return cronexpr.nextMonth(time.Date( return expr.nextMonth(time.Date(
t.Year(), t.Year(),
time.Month(cronexpr.monthList[i]), time.Month(expr.monthList[i]),
1, 1,
cronexpr.hourList[0], expr.hourList[0],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
time.Local)) time.Local))
} }
return time.Date( return time.Date(
t.Year(), t.Year(),
time.Month(cronexpr.monthList[i]), time.Month(expr.monthList[i]),
cronexpr.actualDaysOfMonthList[0], expr.actualDaysOfMonthList[0],
cronexpr.hourList[0], expr.hourList[0],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
time.Local) time.Local)
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int { func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int {
actualDaysOfMonthMap := make(map[int]bool) actualDaysOfMonthMap := make(map[int]bool)
timeOrigin := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) timeOrigin := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
lastDayOfMonth := timeOrigin.AddDate(0, 1, -1).Day() lastDayOfMonth := timeOrigin.AddDate(0, 1, -1).Day()
@ -285,13 +285,13 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
// "fields - day of month, and day of week. If both fields are // "fields - day of month, and day of week. If both fields are
// "restricted (ie, aren't *), the command will be run when // "restricted (ie, aren't *), the command will be run when
// "either field matches the current time" // "either field matches the current time"
if cronexpr.daysOfMonthRestricted || cronexpr.daysOfWeekRestricted == false { if expr.daysOfMonthRestricted || expr.daysOfWeekRestricted == false {
// Last day of month // Last day of month
if cronexpr.lastDayOfMonth { if expr.lastDayOfMonth {
actualDaysOfMonthMap[lastDayOfMonth] = true actualDaysOfMonthMap[lastDayOfMonth] = true
} }
// Days of month // Days of month
for v, _ := range cronexpr.daysOfMonth { for v, _ := range expr.daysOfMonth {
// Ignore days beyond end of month // Ignore days beyond end of month
if v <= lastDayOfMonth { if v <= lastDayOfMonth {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -299,7 +299,7 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
} }
// Work days of month // Work days of month
// As per Wikipedia: month boundaries are not crossed. // As per Wikipedia: month boundaries are not crossed.
for v, _ := range cronexpr.workdaysOfMonth { for v, _ := range expr.workdaysOfMonth {
// Ignore days beyond end of month // Ignore days beyond end of month
if v <= lastDayOfMonth { if v <= lastDayOfMonth {
// If saturday, then friday // If saturday, then friday
@ -322,14 +322,14 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
} }
} }
if cronexpr.daysOfWeekRestricted { if expr.daysOfWeekRestricted {
// How far first sunday is from first day of month // How far first sunday is from first day of month
offset := 7 - int(timeOrigin.Weekday()) offset := 7 - int(timeOrigin.Weekday())
// days of week // days of week
// offset : (7 - day_of_week_of_1st_day_of_month) // offset : (7 - day_of_week_of_1st_day_of_month)
// target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7
for w := 0; w <= 4; w += 1 { for w := 0; w <= 4; w += 1 {
for v, _ := range cronexpr.daysOfWeek { for v, _ := range expr.daysOfWeek {
v := 1 + w*7 + (offset+v)%7 v := 1 + w*7 + (offset+v)%7
if v <= lastDayOfMonth { if v <= lastDayOfMonth {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -339,7 +339,7 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
// days of week of specific week in the month // days of week of specific week in the month
// offset : (7 - day_of_week_of_1st_day_of_month) // offset : (7 - day_of_week_of_1st_day_of_month)
// target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7
for v, _ := range cronexpr.specificWeekDaysOfWeek { for v, _ := range expr.specificWeekDaysOfWeek {
v := 1 + 7*(v/7) + (offset+v)%7 v := 1 + 7*(v/7) + (offset+v)%7
if v <= lastDayOfMonth { if v <= lastDayOfMonth {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -348,7 +348,7 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
// Last days of week of the month // Last days of week of the month
lastWeekOrigin := timeOrigin.AddDate(0, 1, -7) lastWeekOrigin := timeOrigin.AddDate(0, 1, -7)
offset = 7 - int(lastWeekOrigin.Weekday()) offset = 7 - int(lastWeekOrigin.Weekday())
for v, _ := range cronexpr.lastWeekDaysOfWeek { for v, _ := range expr.lastWeekDaysOfWeek {
v := lastWeekOrigin.Day() + (offset+v)%7 v := lastWeekOrigin.Day() + (offset+v)%7
if v <= lastDayOfMonth { if v <= lastDayOfMonth {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -361,54 +361,54 @@ func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextDayOfMonth(t time.Time) time.Time { func (expr *Expression) nextDayOfMonth(t time.Time) time.Time {
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate day of month // candidate day of month
i := sort.SearchInts(cronexpr.actualDaysOfMonthList, t.Day()+1) i := sort.SearchInts(expr.actualDaysOfMonthList, t.Day()+1)
if i == len(cronexpr.actualDaysOfMonthList) { if i == len(expr.actualDaysOfMonthList) {
return cronexpr.nextMonth(t) return expr.nextMonth(t)
} }
return time.Date( return time.Date(
t.Year(), t.Year(),
t.Month(), t.Month(),
cronexpr.actualDaysOfMonthList[i], expr.actualDaysOfMonthList[i],
cronexpr.hourList[0], expr.hourList[0],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
t.Location()) t.Location())
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextHour(t time.Time) time.Time { func (expr *Expression) nextHour(t time.Time) time.Time {
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate hour // candidate hour
i := sort.SearchInts(cronexpr.hourList, t.Hour()+1) i := sort.SearchInts(expr.hourList, t.Hour()+1)
if i == len(cronexpr.hourList) { if i == len(expr.hourList) {
return cronexpr.nextDayOfMonth(t) return expr.nextDayOfMonth(t)
} }
return time.Date( return time.Date(
t.Year(), t.Year(),
t.Month(), t.Month(),
t.Day(), t.Day(),
cronexpr.hourList[i], expr.hourList[i],
cronexpr.minuteList[0], expr.minuteList[0],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
t.Location()) t.Location())
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextMinute(t time.Time) time.Time { func (expr *Expression) nextMinute(t time.Time) time.Time {
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate minute // candidate minute
i := sort.SearchInts(cronexpr.minuteList, t.Minute()+1) i := sort.SearchInts(expr.minuteList, t.Minute()+1)
if i == len(cronexpr.minuteList) { if i == len(expr.minuteList) {
return cronexpr.nextHour(t) return expr.nextHour(t)
} }
return time.Date( return time.Date(
@ -416,23 +416,23 @@ func (cronexpr *Expression) nextMinute(t time.Time) time.Time {
t.Month(), t.Month(),
t.Day(), t.Day(),
t.Hour(), t.Hour(),
cronexpr.minuteList[i], expr.minuteList[i],
cronexpr.secondList[0], expr.secondList[0],
0, 0,
t.Location()) t.Location())
} }
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) nextSecond(t time.Time) time.Time { func (expr *Expression) nextSecond(t time.Time) time.Time {
// nextSecond() assumes all other fields are exactly matched // nextSecond() assumes all other fields are exactly matched
// to the cron expression // to the cron expression
// Find index at which item in list is greater or equal to // Find index at which item in list is greater or equal to
// candidate second // candidate second
i := sort.SearchInts(cronexpr.secondList, t.Second()+1) i := sort.SearchInts(expr.secondList, t.Second()+1)
if i == len(cronexpr.secondList) { if i == len(expr.secondList) {
return cronexpr.nextMinute(t) return expr.nextMinute(t)
} }
return time.Date( return time.Date(
@ -441,7 +441,7 @@ func (cronexpr *Expression) nextSecond(t time.Time) time.Time {
t.Day(), t.Day(),
t.Hour(), t.Hour(),
t.Minute(), t.Minute(),
cronexpr.secondList[i], expr.secondList[i],
0, 0,
t.Location()) t.Location())
} }
@ -504,11 +504,11 @@ func cronNormalize(cronLine string) string {
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) dayofweekFieldParse(cronField string) error { func (expr *Expression) dayofweekFieldParse(cronField string) error {
// Defaults // Defaults
cronexpr.daysOfWeekRestricted = true expr.daysOfWeekRestricted = true
cronexpr.lastWeekDaysOfWeek = make(map[int]bool) expr.lastWeekDaysOfWeek = make(map[int]bool)
cronexpr.daysOfWeek = make(map[int]bool) expr.daysOfWeek = make(map[int]bool)
// "You can also mix all of the above, as in: 1-5,10,12,20-30/5" // "You can also mix all of the above, as in: 1-5,10,12,20-30/5"
cronList := strings.Split(cronField, ",") cronList := strings.Split(cronField, ",")
@ -517,8 +517,8 @@ func (cronexpr *Expression) dayofweekFieldParse(cronField string) error {
step, s := extractInterval(s) step, s := extractInterval(s)
// "*" // "*"
if s == "*" { if s == "*" {
cronexpr.daysOfWeekRestricted = (step > 1) expr.daysOfWeekRestricted = (step > 1)
populateMany(cronexpr.daysOfWeek, 0, 6, step) populateMany(expr.daysOfWeek, 0, 6, step)
continue continue
} }
// "-" // "-"
@ -527,14 +527,14 @@ func (cronexpr *Expression) dayofweekFieldParse(cronField string) error {
if i >= 0 { if i >= 0 {
min := atoi(s[:i]) % 7 min := atoi(s[:i]) % 7
max := atoi(s[i+1:]) % 7 max := atoi(s[i+1:]) % 7
populateMany(cronexpr.daysOfWeek, min, max, step) populateMany(expr.daysOfWeek, min, max, step)
continue continue
} }
// single value // single value
// "l": week day for last week // "l": week day for last week
i = strings.Index(s, "l") i = strings.Index(s, "l")
if i >= 0 { if i >= 0 {
populateOne(cronexpr.lastWeekDaysOfWeek, atoi(s[:i])%7) populateOne(expr.lastWeekDaysOfWeek, atoi(s[:i])%7)
continue continue
} }
// "#": week day for specific week // "#": week day for specific week
@ -545,18 +545,18 @@ func (cronexpr *Expression) dayofweekFieldParse(cronField string) error {
w := atoi(s[i+1:]) w := atoi(s[i+1:])
// v domain = [0,7] // v domain = [0,7]
// w domain = [1,5] // w domain = [1,5]
populateOne(cronexpr.specificWeekDaysOfWeek, (w-1)*7+(v%7)) populateOne(expr.specificWeekDaysOfWeek, (w-1)*7+(v%7))
continue continue
} }
// week day interval for all weeks // week day interval for all weeks
if step > 0 { if step > 0 {
v := atoi(s) % 7 v := atoi(s) % 7
populateMany(cronexpr.daysOfWeek, v, 6, step) populateMany(expr.daysOfWeek, v, 6, step)
continue continue
} }
// single week day for all weeks // single week day for all weeks
v := atoi(s) % 7 v := atoi(s) % 7
populateOne(cronexpr.daysOfWeek, v) populateOne(expr.daysOfWeek, v)
} }
return nil return nil
@ -564,13 +564,13 @@ func (cronexpr *Expression) dayofweekFieldParse(cronField string) error {
/******************************************************************************/ /******************************************************************************/
func (cronexpr *Expression) dayofmonthFieldParse(cronField string) error { func (expr *Expression) dayofmonthFieldParse(cronField string) error {
// Defaults // Defaults
cronexpr.daysOfMonthRestricted = true expr.daysOfMonthRestricted = true
cronexpr.lastDayOfMonth = false expr.lastDayOfMonth = false
cronexpr.daysOfMonth = make(map[int]bool) // days of month map expr.daysOfMonth = make(map[int]bool) // days of month map
cronexpr.workdaysOfMonth = make(map[int]bool) // work day of month map expr.workdaysOfMonth = make(map[int]bool) // work day of month map
// Comma separator is used to mix different allowed syntax // Comma separator is used to mix different allowed syntax
cronList := strings.Split(cronField, ",") cronList := strings.Split(cronField, ",")
@ -579,35 +579,35 @@ func (cronexpr *Expression) dayofmonthFieldParse(cronField string) error {
step, s := extractInterval(s) step, s := extractInterval(s)
// "*" // "*"
if s == "*" { if s == "*" {
cronexpr.daysOfMonthRestricted = (step > 1) expr.daysOfMonthRestricted = (step > 1)
populateMany(cronexpr.daysOfMonth, 1, 31, step) populateMany(expr.daysOfMonth, 1, 31, step)
continue continue
} }
// "-" // "-"
i := strings.Index(s, "-") i := strings.Index(s, "-")
if i >= 0 { if i >= 0 {
populateMany(cronexpr.daysOfMonth, atoi(s[:i]), atoi(s[i+1:]), step) populateMany(expr.daysOfMonth, atoi(s[:i]), atoi(s[i+1:]), step)
continue continue
} }
// single value // single value
// "l": last day of month // "l": last day of month
if s == "l" { if s == "l" {
cronexpr.lastDayOfMonth = true expr.lastDayOfMonth = true
continue continue
} }
// "w": week day // "w": week day
i = strings.Index(s, "w") i = strings.Index(s, "w")
if i >= 0 { if i >= 0 {
populateOne(cronexpr.workdaysOfMonth, atoi(s[:i])) populateOne(expr.workdaysOfMonth, atoi(s[:i]))
continue continue
} }
// single value with interval // single value with interval
if step > 0 { if step > 0 {
populateMany(cronexpr.daysOfMonth, atoi(s), 31, step) populateMany(expr.daysOfMonth, atoi(s), 31, step)
continue continue
} }
// single value // single value
populateOne(cronexpr.daysOfMonth, atoi(s)) populateOne(expr.daysOfMonth, atoi(s))
} }
return nil return nil