diff --git a/cronexpr.go b/cronexpr.go index 58b518f..48236e6 100644 --- a/cronexpr.go +++ b/cronexpr.go @@ -26,22 +26,22 @@ import ( // A Expression represents a specific cron time expression as defined at // type Expression struct { - expression string - secondList []int - minuteList []int - hourList []int - daysOfMonth map[int]bool - workdaysOfMonth map[int]bool - lastDayOfMonth bool - lastWorkdayOfMonth bool - daysOfMonthRestricted bool - actualDaysOfMonthList []int - monthList []int - daysOfWeek map[int]bool - specificWeekDaysOfWeek map[int]bool - lastWeekDaysOfWeek map[int]bool - daysOfWeekRestricted bool - yearList []int + Expression string + SecondList []int + MinuteList []int + HourList []int + DaysOfMonth map[int]bool + WorkdaysOfMonth map[int]bool + LastDayOfMonth bool + LastWorkdayOfMonth bool + DaysOfMonthRestricted bool + ActualDaysOfMonthList []int + MonthList []int + DaysOfWeek map[int]bool + SpecificWeekDaysOfWeek map[int]bool + LastWeekDaysOfWeek map[int]bool + DaysOfWeekRestricted bool + YearList []int } /******************************************************************************/ @@ -93,7 +93,7 @@ func Parse(cronLine string) (*Expression, error) { } field += 1 } else { - expr.secondList = []int{0} + expr.SecondList = []int{0} } // minute field @@ -138,7 +138,7 @@ func Parse(cronLine string) (*Expression, error) { return nil, err } } else { - expr.yearList = yearDescriptor.defaultList + expr.YearList = yearDescriptor.defaultList } return &expr, nil @@ -172,59 +172,59 @@ func (expr *Expression) Next(fromTime time.Time) time.Time { // year v := fromTime.Year() - i := sort.SearchInts(expr.yearList, v) - if i == len(expr.yearList) { + i := sort.SearchInts(expr.YearList, v) + if i == len(expr.YearList) { return time.Time{} } - if v != expr.yearList[i] { + if v != expr.YearList[i] { return expr.nextYear(fromTime) } // month v = int(fromTime.Month()) - i = sort.SearchInts(expr.monthList, v) - if i == len(expr.monthList) { + i = sort.SearchInts(expr.MonthList, v) + if i == len(expr.MonthList) { return expr.nextYear(fromTime) } - if v != expr.monthList[i] { + if v != expr.MonthList[i] { return expr.nextMonth(fromTime) } - expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month())) - if len(expr.actualDaysOfMonthList) == 0 { + expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month())) + if len(expr.ActualDaysOfMonthList) == 0 { return expr.nextMonth(fromTime) } // day of month v = fromTime.Day() - i = sort.SearchInts(expr.actualDaysOfMonthList, v) - if i == len(expr.actualDaysOfMonthList) { + i = sort.SearchInts(expr.ActualDaysOfMonthList, v) + if i == len(expr.ActualDaysOfMonthList) { return expr.nextMonth(fromTime) } - if v != expr.actualDaysOfMonthList[i] { + if v != expr.ActualDaysOfMonthList[i] { return expr.nextDayOfMonth(fromTime) } // hour v = fromTime.Hour() - i = sort.SearchInts(expr.hourList, v) - if i == len(expr.hourList) { + i = sort.SearchInts(expr.HourList, v) + if i == len(expr.HourList) { return expr.nextDayOfMonth(fromTime) } - if v != expr.hourList[i] { + if v != expr.HourList[i] { return expr.nextHour(fromTime) } // minute v = fromTime.Minute() - i = sort.SearchInts(expr.minuteList, v) - if i == len(expr.minuteList) { + i = sort.SearchInts(expr.MinuteList, v) + if i == len(expr.MinuteList) { return expr.nextHour(fromTime) } - if v != expr.minuteList[i] { + if v != expr.MinuteList[i] { return expr.nextMinute(fromTime) } // second v = fromTime.Second() - i = sort.SearchInts(expr.secondList, v) - if i == len(expr.secondList) { + i = sort.SearchInts(expr.SecondList, v) + if i == len(expr.SecondList) { return expr.nextMinute(fromTime) } diff --git a/cronexpr_next.go b/cronexpr_next.go index a0ebdb6..e7e45c5 100644 --- a/cronexpr_next.go +++ b/cronexpr_next.go @@ -36,30 +36,30 @@ var dowNormalizedOffsets = [][]int{ func (expr *Expression) nextYear(t time.Time) time.Time { // Find index at which item in list is greater or equal to // candidate year - i := sort.SearchInts(expr.yearList, t.Year()+1) - if i == len(expr.yearList) { + i := sort.SearchInts(expr.YearList, t.Year()+1) + if i == len(expr.YearList) { return time.Time{} } // Year changed, need to recalculate actual days of month - expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.yearList[i], expr.monthList[0]) - if len(expr.actualDaysOfMonthList) == 0 { + expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.YearList[i], expr.MonthList[0]) + if len(expr.ActualDaysOfMonthList) == 0 { return expr.nextMonth(time.Date( - expr.yearList[i], - time.Month(expr.monthList[0]), + expr.YearList[i], + time.Month(expr.MonthList[0]), 1, - expr.hourList[0], - expr.minuteList[0], - expr.secondList[0], + expr.HourList[0], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location())) } return time.Date( - expr.yearList[i], - time.Month(expr.monthList[0]), - expr.actualDaysOfMonthList[0], - expr.hourList[0], - expr.minuteList[0], - expr.secondList[0], + expr.YearList[i], + time.Month(expr.MonthList[0]), + expr.ActualDaysOfMonthList[0], + expr.HourList[0], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location()) } @@ -69,31 +69,31 @@ func (expr *Expression) nextYear(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 // candidate month - i := sort.SearchInts(expr.monthList, int(t.Month())+1) - if i == len(expr.monthList) { + i := sort.SearchInts(expr.MonthList, int(t.Month())+1) + if i == len(expr.MonthList) { return expr.nextYear(t) } // Month changed, need to recalculate actual days of month - expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.monthList[i]) - if len(expr.actualDaysOfMonthList) == 0 { + expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.MonthList[i]) + if len(expr.ActualDaysOfMonthList) == 0 { return expr.nextMonth(time.Date( t.Year(), - time.Month(expr.monthList[i]), + time.Month(expr.MonthList[i]), 1, - expr.hourList[0], - expr.minuteList[0], - expr.secondList[0], + expr.HourList[0], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location())) } return time.Date( t.Year(), - time.Month(expr.monthList[i]), - expr.actualDaysOfMonthList[0], - expr.hourList[0], - expr.minuteList[0], - expr.secondList[0], + time.Month(expr.MonthList[i]), + expr.ActualDaysOfMonthList[0], + expr.HourList[0], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location()) } @@ -103,18 +103,18 @@ func (expr *Expression) nextMonth(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 // candidate day of month - i := sort.SearchInts(expr.actualDaysOfMonthList, t.Day()+1) - if i == len(expr.actualDaysOfMonthList) { + i := sort.SearchInts(expr.ActualDaysOfMonthList, t.Day()+1) + if i == len(expr.ActualDaysOfMonthList) { return expr.nextMonth(t) } return time.Date( t.Year(), t.Month(), - expr.actualDaysOfMonthList[i], - expr.hourList[0], - expr.minuteList[0], - expr.secondList[0], + expr.ActualDaysOfMonthList[i], + expr.HourList[0], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location()) } @@ -124,8 +124,8 @@ func (expr *Expression) nextDayOfMonth(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 // candidate hour - i := sort.SearchInts(expr.hourList, t.Hour()+1) - if i == len(expr.hourList) { + i := sort.SearchInts(expr.HourList, t.Hour()+1) + if i == len(expr.HourList) { return expr.nextDayOfMonth(t) } @@ -133,9 +133,9 @@ func (expr *Expression) nextHour(t time.Time) time.Time { t.Year(), t.Month(), t.Day(), - expr.hourList[i], - expr.minuteList[0], - expr.secondList[0], + expr.HourList[i], + expr.MinuteList[0], + expr.SecondList[0], 0, t.Location()) } @@ -145,8 +145,8 @@ func (expr *Expression) nextHour(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 // candidate minute - i := sort.SearchInts(expr.minuteList, t.Minute()+1) - if i == len(expr.minuteList) { + i := sort.SearchInts(expr.MinuteList, t.Minute()+1) + if i == len(expr.MinuteList) { return expr.nextHour(t) } @@ -155,8 +155,8 @@ func (expr *Expression) nextMinute(t time.Time) time.Time { t.Month(), t.Day(), t.Hour(), - expr.minuteList[i], - expr.secondList[0], + expr.MinuteList[i], + expr.SecondList[0], 0, t.Location()) } @@ -169,8 +169,8 @@ func (expr *Expression) nextSecond(t time.Time) time.Time { // Find index at which item in list is greater or equal to // candidate second - i := sort.SearchInts(expr.secondList, t.Second()+1) - if i == len(expr.secondList) { + i := sort.SearchInts(expr.SecondList, t.Second()+1) + if i == len(expr.SecondList) { return expr.nextMinute(t) } @@ -180,7 +180,7 @@ func (expr *Expression) nextSecond(t time.Time) time.Time { t.Day(), t.Hour(), t.Minute(), - expr.secondList[i], + expr.SecondList[i], 0, t.Location()) } @@ -199,22 +199,22 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { // "either field matches the current time" // If both fields are not restricted, all days of the month are a hit - if expr.daysOfMonthRestricted == false && expr.daysOfWeekRestricted == false { + if expr.DaysOfMonthRestricted == false && expr.DaysOfWeekRestricted == false { return genericDefaultList[1 : lastDayOfMonth.Day()+1] } // day-of-month != `*` - if expr.daysOfMonthRestricted { + if expr.DaysOfMonthRestricted { // Last day of month - if expr.lastDayOfMonth { + if expr.LastDayOfMonth { actualDaysOfMonthMap[lastDayOfMonth.Day()] = true } // Last work day of month - if expr.lastWorkdayOfMonth { + if expr.LastWorkdayOfMonth { actualDaysOfMonthMap[workdayOfMonth(lastDayOfMonth, lastDayOfMonth)] = true } // Days of month - for v := range expr.daysOfMonth { + for v := range expr.DaysOfMonth { // Ignore days beyond end of month if v <= lastDayOfMonth.Day() { actualDaysOfMonthMap[v] = true @@ -222,7 +222,7 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { } // Work days of month // As per Wikipedia: month boundaries are not crossed. - for v := range expr.workdaysOfMonth { + for v := range expr.WorkdaysOfMonth { // Ignore days beyond end of month if v <= lastDayOfMonth.Day() { actualDaysOfMonthMap[workdayOfMonth(firstDayOfMonth.AddDate(0, 0, v-1), lastDayOfMonth)] = true @@ -231,13 +231,13 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { } // day-of-week != `*` - if expr.daysOfWeekRestricted { + if expr.DaysOfWeekRestricted { // How far first sunday is from first day of month offset := 7 - int(firstDayOfMonth.Weekday()) // days of week // offset : (7 - day_of_week_of_1st_day_of_month) // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 - for v := range expr.daysOfWeek { + for v := range expr.DaysOfWeek { w := dowNormalizedOffsets[(offset+v)%7] actualDaysOfMonthMap[w[0]] = true actualDaysOfMonthMap[w[1]] = true @@ -250,7 +250,7 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { // days of week of specific week in the month // offset : (7 - day_of_week_of_1st_day_of_month) // target : 1 + (7 * week_of_month) + (offset + day_of_week) % 7 - for v := range expr.specificWeekDaysOfWeek { + for v := range expr.SpecificWeekDaysOfWeek { v = 1 + 7*(v/7) + (offset+v)%7 if v <= lastDayOfMonth.Day() { actualDaysOfMonthMap[v] = true @@ -259,7 +259,7 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int { // Last days of week of the month lastWeekOrigin := firstDayOfMonth.AddDate(0, 1, -7) offset = 7 - int(lastWeekOrigin.Weekday()) - for v := range expr.lastWeekDaysOfWeek { + for v := range expr.LastWeekDaysOfWeek { v = lastWeekOrigin.Day() + (offset+v)%7 if v <= lastDayOfMonth.Day() { actualDaysOfMonthMap[v] = true diff --git a/cronexpr_parse.go b/cronexpr_parse.go index a9fe746..27c9f63 100644 --- a/cronexpr_parse.go +++ b/cronexpr_parse.go @@ -212,7 +212,7 @@ var cronNormalizer = strings.NewReplacer( func (expr *Expression) secondFieldHandler(s string) error { var err error - expr.secondList, err = genericFieldHandler(s, secondDescriptor) + expr.SecondList, err = genericFieldHandler(s, secondDescriptor) return err } @@ -220,7 +220,7 @@ func (expr *Expression) secondFieldHandler(s string) error { func (expr *Expression) minuteFieldHandler(s string) error { var err error - expr.minuteList, err = genericFieldHandler(s, minuteDescriptor) + expr.MinuteList, err = genericFieldHandler(s, minuteDescriptor) return err } @@ -228,7 +228,7 @@ func (expr *Expression) minuteFieldHandler(s string) error { func (expr *Expression) hourFieldHandler(s string) error { var err error - expr.hourList, err = genericFieldHandler(s, hourDescriptor) + expr.HourList, err = genericFieldHandler(s, hourDescriptor) return err } @@ -236,7 +236,7 @@ func (expr *Expression) hourFieldHandler(s string) error { func (expr *Expression) monthFieldHandler(s string) error { var err error - expr.monthList, err = genericFieldHandler(s, monthDescriptor) + expr.MonthList, err = genericFieldHandler(s, monthDescriptor) return err } @@ -244,7 +244,7 @@ func (expr *Expression) monthFieldHandler(s string) error { func (expr *Expression) yearFieldHandler(s string) error { var err error - expr.yearList, err = genericFieldHandler(s, yearDescriptor) + expr.YearList, err = genericFieldHandler(s, yearDescriptor) return err } @@ -288,10 +288,10 @@ func genericFieldHandler(s string, desc fieldDescriptor) ([]int, error) { } func (expr *Expression) dowFieldHandler(s string) error { - expr.daysOfWeekRestricted = true - expr.daysOfWeek = make(map[int]bool) - expr.lastWeekDaysOfWeek = make(map[int]bool) - expr.specificWeekDaysOfWeek = make(map[int]bool) + expr.DaysOfWeekRestricted = true + expr.DaysOfWeek = make(map[int]bool) + expr.LastWeekDaysOfWeek = make(map[int]bool) + expr.SpecificWeekDaysOfWeek = make(map[int]bool) directives, err := genericFieldParse(s, dowDescriptor) if err != nil { @@ -306,34 +306,34 @@ func (expr *Expression) dowFieldHandler(s string) error { // `5L` pairs := makeLayoutRegexp(layoutDowOfLastWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) if len(pairs) > 0 { - populateOne(expr.lastWeekDaysOfWeek, dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])) + populateOne(expr.LastWeekDaysOfWeek, dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])) } else { // `5#3` pairs := makeLayoutRegexp(layoutDowOfSpecificWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) if len(pairs) > 0 { - populateOne(expr.specificWeekDaysOfWeek, (dowDescriptor.atoi(snormal[pairs[4]:pairs[5]])-1)*7+(dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])%7)) + populateOne(expr.SpecificWeekDaysOfWeek, (dowDescriptor.atoi(snormal[pairs[4]:pairs[5]])-1)*7+(dowDescriptor.atoi(snormal[pairs[2]:pairs[3]])%7)) } else { return fmt.Errorf("syntax error in day-of-week field: '%s'", sdirective) } } case one: - populateOne(expr.daysOfWeek, directive.first) + populateOne(expr.DaysOfWeek, directive.first) case span: - populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) + populateMany(expr.DaysOfWeek, directive.first, directive.last, directive.step) case all: - populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) - expr.daysOfWeekRestricted = false + populateMany(expr.DaysOfWeek, directive.first, directive.last, directive.step) + expr.DaysOfWeekRestricted = false } } return nil } func (expr *Expression) domFieldHandler(s string) error { - expr.daysOfMonthRestricted = true - expr.lastDayOfMonth = false - expr.lastWorkdayOfMonth = false - expr.daysOfMonth = make(map[int]bool) // days of month map - expr.workdaysOfMonth = make(map[int]bool) // work days of month map + expr.DaysOfMonthRestricted = true + expr.LastDayOfMonth = false + expr.LastWorkdayOfMonth = false + expr.DaysOfMonth = make(map[int]bool) // days of month map + expr.WorkdaysOfMonth = make(map[int]bool) // work days of month map directives, err := genericFieldParse(s, domDescriptor) if err != nil { @@ -347,28 +347,28 @@ func (expr *Expression) domFieldHandler(s string) error { snormal := strings.ToLower(sdirective) // `L` if makeLayoutRegexp(layoutLastDom, domDescriptor.valuePattern).MatchString(snormal) { - expr.lastDayOfMonth = true + expr.LastDayOfMonth = true } else { // `LW` if makeLayoutRegexp(layoutLastWorkdom, domDescriptor.valuePattern).MatchString(snormal) { - expr.lastWorkdayOfMonth = true + expr.LastWorkdayOfMonth = true } else { // `15W` pairs := makeLayoutRegexp(layoutWorkdom, domDescriptor.valuePattern).FindStringSubmatchIndex(snormal) if len(pairs) > 0 { - populateOne(expr.workdaysOfMonth, domDescriptor.atoi(snormal[pairs[2]:pairs[3]])) + populateOne(expr.WorkdaysOfMonth, domDescriptor.atoi(snormal[pairs[2]:pairs[3]])) } else { return fmt.Errorf("syntax error in day-of-month field: '%s'", sdirective) } } } case one: - populateOne(expr.daysOfMonth, directive.first) + populateOne(expr.DaysOfMonth, directive.first) case span: - populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) + populateMany(expr.DaysOfMonth, directive.first, directive.last, directive.step) case all: - populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) - expr.daysOfMonthRestricted = false + populateMany(expr.DaysOfMonth, directive.first, directive.last, directive.step) + expr.DaysOfMonthRestricted = false } } return nil