Refactor some on-spec logic into helper types
This commit is contained in:
parent
d0dbc19799
commit
74b6d40774
79
core/cron.go
79
core/cron.go
@ -80,17 +80,63 @@ var weekdays = map[string]time.Weekday{
|
|||||||
"Sat": time.Saturday,
|
"Sat": time.Saturday,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ymd struct {
|
||||||
|
Year int
|
||||||
|
Month time.Month
|
||||||
|
Day int
|
||||||
|
}
|
||||||
|
|
||||||
|
type onSpecDate interface {
|
||||||
|
getDates(base time.Time) []ymd
|
||||||
|
}
|
||||||
|
|
||||||
|
type onSpecWeekday struct {
|
||||||
|
weekday time.Weekday
|
||||||
|
}
|
||||||
|
|
||||||
|
func (date *onSpecWeekday) getDates(base time.Time) (dates []ymd) {
|
||||||
|
// For a weekday, add the next of that weekday 0-6 days ahead and 7-13 days ahead.
|
||||||
|
// The first date ensures that we don't miss multiple updates on the same day of the week
|
||||||
|
// (e.g. "on Sun at 06:00,18:00") and the second date ensures that we don't get stuck with
|
||||||
|
// only a date in the past (e.g. "on Sun at 02:00" when base is Sun 03:00).
|
||||||
|
daysForward := (int(date.weekday) - int(base.Weekday()) + 7) % 7 // value in [0,6]
|
||||||
|
day0_6 := base.AddDate(0, 0, daysForward)
|
||||||
|
dates = append(dates, ymd{day0_6.Year(), day0_6.Month(), day0_6.Day()})
|
||||||
|
day7_13 := base.AddDate(0, 0, daysForward+7)
|
||||||
|
dates = append(dates, ymd{day7_13.Year(), day7_13.Month(), day7_13.Day()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type onSpecEveryMonth struct {
|
||||||
|
day int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (date *onSpecEveryMonth) getDates(base time.Time) (dates []ymd) {
|
||||||
|
// For every-month, add the date for the current month and the date for the next month.
|
||||||
|
dates = append(dates, ymd{base.Year(), base.Month(), date.day})
|
||||||
|
nextMonth := base.AddDate(0, 1, 0)
|
||||||
|
dates = append(dates, ymd{nextMonth.Year(), nextMonth.Month(), date.day})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type onSpecMonthDay struct {
|
||||||
|
month int
|
||||||
|
day int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (date *onSpecMonthDay) getDates(base time.Time) (dates []ymd) {
|
||||||
|
// For month/day, add the date for the base year and the next year.
|
||||||
|
dates = append(dates, ymd{base.Year(), time.Month(date.month), date.day})
|
||||||
|
dates = append(dates, ymd{base.Year() + 1, time.Month(date.month), date.day})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get the next instances of the on-spec times after the base time.
|
// Get the next instances of the on-spec times after the base time.
|
||||||
// An on-spec is in the pattern DOW[,DOW[...]] where DOW is an abbreviated weekday
|
// An on-spec is in the pattern DOW[,DOW[...]] where DOW is an abbreviated weekday
|
||||||
// or M/D[,M/D[...]] where M/D is a month and day.
|
// or M/D[,M/D[...]] where M/D is a month and day.
|
||||||
// As a special case, "*/N" matches the Nth day of every month.
|
// As a special case, "*/N" matches the Nth day of every month.
|
||||||
// An on-spec may be followed by an at-spec; otherwise, "at 00:00" is implied.
|
// An on-spec may be followed by an at-spec; otherwise, "at 00:00" is implied.
|
||||||
func parseOnSpec(base time.Time, onSpec string) (nextUpdates []time.Time, err error) {
|
func parseOnSpec(base time.Time, onSpec string) (nextUpdates []time.Time, err error) {
|
||||||
type Date struct {
|
|
||||||
Year int
|
|
||||||
Month time.Month
|
|
||||||
Day int
|
|
||||||
}
|
|
||||||
type Time struct {
|
type Time struct {
|
||||||
Hour int
|
Hour int
|
||||||
Minute int
|
Minute int
|
||||||
@ -111,38 +157,27 @@ func parseOnSpec(base time.Time, onSpec string) (nextUpdates []time.Time, err er
|
|||||||
atTimes = append(atTimes, Time{hour, minute})
|
atTimes = append(atTimes, Time{hour, minute})
|
||||||
}
|
}
|
||||||
|
|
||||||
var dates []Date
|
var dates []ymd
|
||||||
for _, daySpec := range strings.Split(onSpec, ",") {
|
for _, daySpec := range strings.Split(onSpec, ",") {
|
||||||
|
var date onSpecDate
|
||||||
if weekday, ok := weekdays[daySpec]; ok {
|
if weekday, ok := weekdays[daySpec]; ok {
|
||||||
// For a weekday, add the next of that weekday 0-6 days ahead and 7-13 days ahead.
|
date = &onSpecWeekday{weekday}
|
||||||
// The first date ensures that we don't miss multiple updates on the same day of the week
|
|
||||||
// (e.g. "on Sun at 06:00,18:00") and the second date ensures that we don't get stuck with
|
|
||||||
// only a date in the past (e.g. "on Sun at 02:00" when base is Sun 03:00).
|
|
||||||
daysForward := (int(weekday) - int(base.Weekday()) + 7) % 7 // value in [0,6]
|
|
||||||
day0_6 := base.AddDate(0, 0, daysForward)
|
|
||||||
dates = append(dates, Date{day0_6.Year(), day0_6.Month(), day0_6.Day()})
|
|
||||||
day7_13 := base.AddDate(0, 0, daysForward+7)
|
|
||||||
dates = append(dates, Date{day7_13.Year(), day7_13.Month(), day7_13.Day()})
|
|
||||||
} else if strings.HasPrefix(daySpec, "*/") {
|
} else if strings.HasPrefix(daySpec, "*/") {
|
||||||
// For every-month, add the date for the current month and the date for the next month.
|
|
||||||
var day int
|
var day int
|
||||||
_, err := fmt.Sscanf(daySpec, "*/%d", &day)
|
_, err := fmt.Sscanf(daySpec, "*/%d", &day)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse month/day %s: %v", daySpec, err)
|
return nil, fmt.Errorf("could not parse month/day %s: %v", daySpec, err)
|
||||||
}
|
}
|
||||||
dates = append(dates, Date{base.Year(), base.Month(), day})
|
date = &onSpecEveryMonth{day}
|
||||||
nextMonth := base.AddDate(0, 1, 0)
|
|
||||||
dates = append(dates, Date{nextMonth.Year(), nextMonth.Month(), day})
|
|
||||||
} else {
|
} else {
|
||||||
// For month/day, add the date for the base year and the next year.
|
|
||||||
var month, day int
|
var month, day int
|
||||||
_, err := fmt.Sscanf(daySpec, "%d/%d", &month, &day)
|
_, err := fmt.Sscanf(daySpec, "%d/%d", &month, &day)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not parse month/day %s: %v", daySpec, err)
|
return nil, fmt.Errorf("could not parse month/day %s: %v", daySpec, err)
|
||||||
}
|
}
|
||||||
dates = append(dates, Date{base.Year(), time.Month(month), day})
|
date = &onSpecMonthDay{month, day}
|
||||||
dates = append(dates, Date{base.Year() + 1, time.Month(month), day})
|
|
||||||
}
|
}
|
||||||
|
dates = append(dates, date.getDates(base)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now, for each date, create a datetime based on the at-spec.
|
// Now, for each date, create a datetime based on the at-spec.
|
||||||
|
Loading…
Reference in New Issue
Block a user