Expose cron expression fields

This commit is contained in:
Bruno Luiz 2018-08-18 13:44:57 -03:00
parent 88b0669f7d
commit 02e4e6fd45
3 changed files with 120 additions and 120 deletions

View File

@ -26,22 +26,22 @@ import (
// A Expression represents a specific cron time expression as defined at // A Expression represents a specific cron time expression as defined at
// <https://github.com/gorhill/cronexpr#implementation> // <https://github.com/gorhill/cronexpr#implementation>
type Expression struct { type Expression struct {
expression string Expression string
secondList []int SecondList []int
minuteList []int MinuteList []int
hourList []int HourList []int
daysOfMonth map[int]bool DaysOfMonth map[int]bool
workdaysOfMonth map[int]bool WorkdaysOfMonth map[int]bool
lastDayOfMonth bool LastDayOfMonth bool
lastWorkdayOfMonth bool LastWorkdayOfMonth bool
daysOfMonthRestricted bool DaysOfMonthRestricted bool
actualDaysOfMonthList []int ActualDaysOfMonthList []int
monthList []int MonthList []int
daysOfWeek map[int]bool DaysOfWeek map[int]bool
specificWeekDaysOfWeek map[int]bool SpecificWeekDaysOfWeek map[int]bool
lastWeekDaysOfWeek map[int]bool LastWeekDaysOfWeek map[int]bool
daysOfWeekRestricted bool DaysOfWeekRestricted bool
yearList []int YearList []int
} }
/******************************************************************************/ /******************************************************************************/
@ -93,7 +93,7 @@ func Parse(cronLine string) (*Expression, error) {
} }
field += 1 field += 1
} else { } else {
expr.secondList = []int{0} expr.SecondList = []int{0}
} }
// minute field // minute field
@ -138,7 +138,7 @@ func Parse(cronLine string) (*Expression, error) {
return nil, err return nil, err
} }
} else { } else {
expr.yearList = yearDescriptor.defaultList expr.YearList = yearDescriptor.defaultList
} }
return &expr, nil return &expr, nil
@ -172,59 +172,59 @@ func (expr *Expression) Next(fromTime time.Time) time.Time {
// year // year
v := fromTime.Year() v := fromTime.Year()
i := sort.SearchInts(expr.yearList, v) i := sort.SearchInts(expr.YearList, v)
if i == len(expr.yearList) { if i == len(expr.YearList) {
return time.Time{} return time.Time{}
} }
if v != expr.yearList[i] { if v != expr.YearList[i] {
return expr.nextYear(fromTime) return expr.nextYear(fromTime)
} }
// month // month
v = int(fromTime.Month()) v = int(fromTime.Month())
i = sort.SearchInts(expr.monthList, v) i = sort.SearchInts(expr.MonthList, v)
if i == len(expr.monthList) { if i == len(expr.MonthList) {
return expr.nextYear(fromTime) return expr.nextYear(fromTime)
} }
if v != expr.monthList[i] { if v != expr.MonthList[i] {
return expr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month())) expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(fromTime.Year(), int(fromTime.Month()))
if len(expr.actualDaysOfMonthList) == 0 { if len(expr.ActualDaysOfMonthList) == 0 {
return expr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
// day of month // day of month
v = fromTime.Day() v = fromTime.Day()
i = sort.SearchInts(expr.actualDaysOfMonthList, v) i = sort.SearchInts(expr.ActualDaysOfMonthList, v)
if i == len(expr.actualDaysOfMonthList) { if i == len(expr.ActualDaysOfMonthList) {
return expr.nextMonth(fromTime) return expr.nextMonth(fromTime)
} }
if v != expr.actualDaysOfMonthList[i] { if v != expr.ActualDaysOfMonthList[i] {
return expr.nextDayOfMonth(fromTime) return expr.nextDayOfMonth(fromTime)
} }
// hour // hour
v = fromTime.Hour() v = fromTime.Hour()
i = sort.SearchInts(expr.hourList, v) i = sort.SearchInts(expr.HourList, v)
if i == len(expr.hourList) { if i == len(expr.HourList) {
return expr.nextDayOfMonth(fromTime) return expr.nextDayOfMonth(fromTime)
} }
if v != expr.hourList[i] { if v != expr.HourList[i] {
return expr.nextHour(fromTime) return expr.nextHour(fromTime)
} }
// minute // minute
v = fromTime.Minute() v = fromTime.Minute()
i = sort.SearchInts(expr.minuteList, v) i = sort.SearchInts(expr.MinuteList, v)
if i == len(expr.minuteList) { if i == len(expr.MinuteList) {
return expr.nextHour(fromTime) return expr.nextHour(fromTime)
} }
if v != expr.minuteList[i] { if v != expr.MinuteList[i] {
return expr.nextMinute(fromTime) return expr.nextMinute(fromTime)
} }
// second // second
v = fromTime.Second() v = fromTime.Second()
i = sort.SearchInts(expr.secondList, v) i = sort.SearchInts(expr.SecondList, v)
if i == len(expr.secondList) { if i == len(expr.SecondList) {
return expr.nextMinute(fromTime) return expr.nextMinute(fromTime)
} }

View File

@ -36,30 +36,30 @@ var dowNormalizedOffsets = [][]int{
func (expr *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(expr.yearList, t.Year()+1) i := sort.SearchInts(expr.YearList, t.Year()+1)
if i == len(expr.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
expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.yearList[i], expr.monthList[0]) expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(expr.YearList[i], expr.MonthList[0])
if len(expr.actualDaysOfMonthList) == 0 { if len(expr.ActualDaysOfMonthList) == 0 {
return expr.nextMonth(time.Date( return expr.nextMonth(time.Date(
expr.yearList[i], expr.YearList[i],
time.Month(expr.monthList[0]), time.Month(expr.MonthList[0]),
1, 1,
expr.hourList[0], expr.HourList[0],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location())) t.Location()))
} }
return time.Date( return time.Date(
expr.yearList[i], expr.YearList[i],
time.Month(expr.monthList[0]), time.Month(expr.MonthList[0]),
expr.actualDaysOfMonthList[0], expr.ActualDaysOfMonthList[0],
expr.hourList[0], expr.HourList[0],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location()) t.Location())
} }
@ -69,31 +69,31 @@ func (expr *Expression) nextYear(t time.Time) time.Time {
func (expr *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(expr.monthList, int(t.Month())+1) i := sort.SearchInts(expr.MonthList, int(t.Month())+1)
if i == len(expr.monthList) { if i == len(expr.MonthList) {
return expr.nextYear(t) return expr.nextYear(t)
} }
// Month changed, need to recalculate actual days of month // Month changed, need to recalculate actual days of month
expr.actualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.monthList[i]) expr.ActualDaysOfMonthList = expr.calculateActualDaysOfMonth(t.Year(), expr.MonthList[i])
if len(expr.actualDaysOfMonthList) == 0 { if len(expr.ActualDaysOfMonthList) == 0 {
return expr.nextMonth(time.Date( return expr.nextMonth(time.Date(
t.Year(), t.Year(),
time.Month(expr.monthList[i]), time.Month(expr.MonthList[i]),
1, 1,
expr.hourList[0], expr.HourList[0],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location())) t.Location()))
} }
return time.Date( return time.Date(
t.Year(), t.Year(),
time.Month(expr.monthList[i]), time.Month(expr.MonthList[i]),
expr.actualDaysOfMonthList[0], expr.ActualDaysOfMonthList[0],
expr.hourList[0], expr.HourList[0],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location()) t.Location())
} }
@ -103,18 +103,18 @@ func (expr *Expression) nextMonth(t time.Time) time.Time {
func (expr *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(expr.actualDaysOfMonthList, t.Day()+1) i := sort.SearchInts(expr.ActualDaysOfMonthList, t.Day()+1)
if i == len(expr.actualDaysOfMonthList) { if i == len(expr.ActualDaysOfMonthList) {
return expr.nextMonth(t) return expr.nextMonth(t)
} }
return time.Date( return time.Date(
t.Year(), t.Year(),
t.Month(), t.Month(),
expr.actualDaysOfMonthList[i], expr.ActualDaysOfMonthList[i],
expr.hourList[0], expr.HourList[0],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location()) t.Location())
} }
@ -124,8 +124,8 @@ func (expr *Expression) nextDayOfMonth(t time.Time) time.Time {
func (expr *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(expr.hourList, t.Hour()+1) i := sort.SearchInts(expr.HourList, t.Hour()+1)
if i == len(expr.hourList) { if i == len(expr.HourList) {
return expr.nextDayOfMonth(t) return expr.nextDayOfMonth(t)
} }
@ -133,9 +133,9 @@ func (expr *Expression) nextHour(t time.Time) time.Time {
t.Year(), t.Year(),
t.Month(), t.Month(),
t.Day(), t.Day(),
expr.hourList[i], expr.HourList[i],
expr.minuteList[0], expr.MinuteList[0],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location()) t.Location())
} }
@ -145,8 +145,8 @@ func (expr *Expression) nextHour(t time.Time) time.Time {
func (expr *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(expr.minuteList, t.Minute()+1) i := sort.SearchInts(expr.MinuteList, t.Minute()+1)
if i == len(expr.minuteList) { if i == len(expr.MinuteList) {
return expr.nextHour(t) return expr.nextHour(t)
} }
@ -155,8 +155,8 @@ func (expr *Expression) nextMinute(t time.Time) time.Time {
t.Month(), t.Month(),
t.Day(), t.Day(),
t.Hour(), t.Hour(),
expr.minuteList[i], expr.MinuteList[i],
expr.secondList[0], expr.SecondList[0],
0, 0,
t.Location()) 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 // Find index at which item in list is greater or equal to
// candidate second // candidate second
i := sort.SearchInts(expr.secondList, t.Second()+1) i := sort.SearchInts(expr.SecondList, t.Second()+1)
if i == len(expr.secondList) { if i == len(expr.SecondList) {
return expr.nextMinute(t) return expr.nextMinute(t)
} }
@ -180,7 +180,7 @@ func (expr *Expression) nextSecond(t time.Time) time.Time {
t.Day(), t.Day(),
t.Hour(), t.Hour(),
t.Minute(), t.Minute(),
expr.secondList[i], expr.SecondList[i],
0, 0,
t.Location()) t.Location())
} }
@ -199,22 +199,22 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int {
// "either field matches the current time" // "either field matches the current time"
// If both fields are not restricted, all days of the month are a hit // 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] return genericDefaultList[1 : lastDayOfMonth.Day()+1]
} }
// day-of-month != `*` // day-of-month != `*`
if expr.daysOfMonthRestricted { if expr.DaysOfMonthRestricted {
// Last day of month // Last day of month
if expr.lastDayOfMonth { if expr.LastDayOfMonth {
actualDaysOfMonthMap[lastDayOfMonth.Day()] = true actualDaysOfMonthMap[lastDayOfMonth.Day()] = true
} }
// Last work day of month // Last work day of month
if expr.lastWorkdayOfMonth { if expr.LastWorkdayOfMonth {
actualDaysOfMonthMap[workdayOfMonth(lastDayOfMonth, lastDayOfMonth)] = true actualDaysOfMonthMap[workdayOfMonth(lastDayOfMonth, lastDayOfMonth)] = true
} }
// Days of month // Days of month
for v := range expr.daysOfMonth { for v := range expr.DaysOfMonth {
// Ignore days beyond end of month // Ignore days beyond end of month
if v <= lastDayOfMonth.Day() { if v <= lastDayOfMonth.Day() {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -222,7 +222,7 @@ func (expr *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 expr.workdaysOfMonth { for v := range expr.WorkdaysOfMonth {
// Ignore days beyond end of month // Ignore days beyond end of month
if v <= lastDayOfMonth.Day() { if v <= lastDayOfMonth.Day() {
actualDaysOfMonthMap[workdayOfMonth(firstDayOfMonth.AddDate(0, 0, v-1), lastDayOfMonth)] = true 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 != `*` // day-of-week != `*`
if expr.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(firstDayOfMonth.Weekday()) offset := 7 - int(firstDayOfMonth.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 v := range expr.daysOfWeek { for v := range expr.DaysOfWeek {
w := dowNormalizedOffsets[(offset+v)%7] w := dowNormalizedOffsets[(offset+v)%7]
actualDaysOfMonthMap[w[0]] = true actualDaysOfMonthMap[w[0]] = true
actualDaysOfMonthMap[w[1]] = 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 // 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 expr.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.Day() { if v <= lastDayOfMonth.Day() {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true
@ -259,7 +259,7 @@ func (expr *Expression) calculateActualDaysOfMonth(year, month int) []int {
// Last days of week of the month // Last days of week of the month
lastWeekOrigin := firstDayOfMonth.AddDate(0, 1, -7) lastWeekOrigin := firstDayOfMonth.AddDate(0, 1, -7)
offset = 7 - int(lastWeekOrigin.Weekday()) offset = 7 - int(lastWeekOrigin.Weekday())
for v := range expr.lastWeekDaysOfWeek { for v := range expr.LastWeekDaysOfWeek {
v = lastWeekOrigin.Day() + (offset+v)%7 v = lastWeekOrigin.Day() + (offset+v)%7
if v <= lastDayOfMonth.Day() { if v <= lastDayOfMonth.Day() {
actualDaysOfMonthMap[v] = true actualDaysOfMonthMap[v] = true

View File

@ -212,7 +212,7 @@ var cronNormalizer = strings.NewReplacer(
func (expr *Expression) secondFieldHandler(s string) error { func (expr *Expression) secondFieldHandler(s string) error {
var err error var err error
expr.secondList, err = genericFieldHandler(s, secondDescriptor) expr.SecondList, err = genericFieldHandler(s, secondDescriptor)
return err return err
} }
@ -220,7 +220,7 @@ func (expr *Expression) secondFieldHandler(s string) error {
func (expr *Expression) minuteFieldHandler(s string) error { func (expr *Expression) minuteFieldHandler(s string) error {
var err error var err error
expr.minuteList, err = genericFieldHandler(s, minuteDescriptor) expr.MinuteList, err = genericFieldHandler(s, minuteDescriptor)
return err return err
} }
@ -228,7 +228,7 @@ func (expr *Expression) minuteFieldHandler(s string) error {
func (expr *Expression) hourFieldHandler(s string) error { func (expr *Expression) hourFieldHandler(s string) error {
var err error var err error
expr.hourList, err = genericFieldHandler(s, hourDescriptor) expr.HourList, err = genericFieldHandler(s, hourDescriptor)
return err return err
} }
@ -236,7 +236,7 @@ func (expr *Expression) hourFieldHandler(s string) error {
func (expr *Expression) monthFieldHandler(s string) error { func (expr *Expression) monthFieldHandler(s string) error {
var err error var err error
expr.monthList, err = genericFieldHandler(s, monthDescriptor) expr.MonthList, err = genericFieldHandler(s, monthDescriptor)
return err return err
} }
@ -244,7 +244,7 @@ func (expr *Expression) monthFieldHandler(s string) error {
func (expr *Expression) yearFieldHandler(s string) error { func (expr *Expression) yearFieldHandler(s string) error {
var err error var err error
expr.yearList, err = genericFieldHandler(s, yearDescriptor) expr.YearList, err = genericFieldHandler(s, yearDescriptor)
return err return err
} }
@ -288,10 +288,10 @@ func genericFieldHandler(s string, desc fieldDescriptor) ([]int, error) {
} }
func (expr *Expression) dowFieldHandler(s string) error { func (expr *Expression) dowFieldHandler(s string) error {
expr.daysOfWeekRestricted = true expr.DaysOfWeekRestricted = true
expr.daysOfWeek = make(map[int]bool) expr.DaysOfWeek = make(map[int]bool)
expr.lastWeekDaysOfWeek = make(map[int]bool) expr.LastWeekDaysOfWeek = make(map[int]bool)
expr.specificWeekDaysOfWeek = make(map[int]bool) expr.SpecificWeekDaysOfWeek = make(map[int]bool)
directives, err := genericFieldParse(s, dowDescriptor) directives, err := genericFieldParse(s, dowDescriptor)
if err != nil { if err != nil {
@ -306,34 +306,34 @@ func (expr *Expression) dowFieldHandler(s string) error {
// `5L` // `5L`
pairs := makeLayoutRegexp(layoutDowOfLastWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) pairs := makeLayoutRegexp(layoutDowOfLastWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal)
if len(pairs) > 0 { 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 { } else {
// `5#3` // `5#3`
pairs := makeLayoutRegexp(layoutDowOfSpecificWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal) pairs := makeLayoutRegexp(layoutDowOfSpecificWeek, dowDescriptor.valuePattern).FindStringSubmatchIndex(snormal)
if len(pairs) > 0 { 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 { } else {
return fmt.Errorf("syntax error in day-of-week field: '%s'", sdirective) return fmt.Errorf("syntax error in day-of-week field: '%s'", sdirective)
} }
} }
case one: case one:
populateOne(expr.daysOfWeek, directive.first) populateOne(expr.DaysOfWeek, directive.first)
case span: case span:
populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) populateMany(expr.DaysOfWeek, directive.first, directive.last, directive.step)
case all: case all:
populateMany(expr.daysOfWeek, directive.first, directive.last, directive.step) populateMany(expr.DaysOfWeek, directive.first, directive.last, directive.step)
expr.daysOfWeekRestricted = false expr.DaysOfWeekRestricted = false
} }
} }
return nil return nil
} }
func (expr *Expression) domFieldHandler(s string) error { func (expr *Expression) domFieldHandler(s string) error {
expr.daysOfMonthRestricted = true expr.DaysOfMonthRestricted = true
expr.lastDayOfMonth = false expr.LastDayOfMonth = false
expr.lastWorkdayOfMonth = false expr.LastWorkdayOfMonth = false
expr.daysOfMonth = make(map[int]bool) // days of month map expr.DaysOfMonth = make(map[int]bool) // days of month map
expr.workdaysOfMonth = make(map[int]bool) // work days of month map expr.WorkdaysOfMonth = make(map[int]bool) // work days of month map
directives, err := genericFieldParse(s, domDescriptor) directives, err := genericFieldParse(s, domDescriptor)
if err != nil { if err != nil {
@ -347,28 +347,28 @@ func (expr *Expression) domFieldHandler(s string) error {
snormal := strings.ToLower(sdirective) snormal := strings.ToLower(sdirective)
// `L` // `L`
if makeLayoutRegexp(layoutLastDom, domDescriptor.valuePattern).MatchString(snormal) { if makeLayoutRegexp(layoutLastDom, domDescriptor.valuePattern).MatchString(snormal) {
expr.lastDayOfMonth = true expr.LastDayOfMonth = true
} else { } else {
// `LW` // `LW`
if makeLayoutRegexp(layoutLastWorkdom, domDescriptor.valuePattern).MatchString(snormal) { if makeLayoutRegexp(layoutLastWorkdom, domDescriptor.valuePattern).MatchString(snormal) {
expr.lastWorkdayOfMonth = true expr.LastWorkdayOfMonth = true
} else { } else {
// `15W` // `15W`
pairs := makeLayoutRegexp(layoutWorkdom, domDescriptor.valuePattern).FindStringSubmatchIndex(snormal) pairs := makeLayoutRegexp(layoutWorkdom, domDescriptor.valuePattern).FindStringSubmatchIndex(snormal)
if len(pairs) > 0 { 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 { } else {
return fmt.Errorf("syntax error in day-of-month field: '%s'", sdirective) return fmt.Errorf("syntax error in day-of-month field: '%s'", sdirective)
} }
} }
} }
case one: case one:
populateOne(expr.daysOfMonth, directive.first) populateOne(expr.DaysOfMonth, directive.first)
case span: case span:
populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) populateMany(expr.DaysOfMonth, directive.first, directive.last, directive.step)
case all: case all:
populateMany(expr.daysOfMonth, directive.first, directive.last, directive.step) populateMany(expr.DaysOfMonth, directive.first, directive.last, directive.step)
expr.daysOfMonthRestricted = false expr.DaysOfMonthRestricted = false
} }
} }
return nil return nil