package crontab import ( "time" ) type minuteNode struct { } func newMinuteNode() *minuteNode { return &minuteNode{} } type hourNode struct { Minute [60]*minuteNode } func (hour *hourNode) CreateMinute(nminute int) { min := &minuteNode{} hour.Minute[nminute] = min } func newHourNode() *hourNode { return &hourNode{} } type dayNode struct { IsClear bool Week time.Weekday Hour [24]*hourNode } func (day *dayNode) CreateHour(nhour int) { hour := &hourNode{} day.Hour[nhour] = hour } func newDayNode(curday *time.Time) *dayNode { day := &dayNode{} week := curday.Weekday() day.Week = week day.IsClear = true return day } type monthNode struct { MaxDay int First *time.Time Day [32]*dayNode } func (month *monthNode) CreateDay(nday int) { day := month.First.AddDate(0, 0, nday-1) month.Day[nday] = newDayNode(&day) } func newMonthNode(year, month int) *monthNode { Month := &monthNode{} First := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local) Month.First = &First Month.MaxDay = Month.First.AddDate(0, 1, -1).Day() return Month } type trieYear struct { Year int Month [13]*monthNode } // CheckYear 跨年判断 func (ty *trieYear) CheckYear() bool { year := time.Now().Year() return ty.Year == year } func (ty *trieYear) clearHour() { for _, month := range ty.Month { if month != nil { for _, day := range month.Day { if day != nil { for i := 0; i <= 23; i++ { day.Hour[i] = nil day.IsClear = true } } } } } } func newTrieYear() *trieYear { ty := trieYear{} ty.Year = time.Now().Year() return &ty } // GetPlanTime 获取计划表 func (ty *trieYear) GetPlanTime(cron *Crontab, aftertime time.Time, count uint) []time.Time { now := aftertime nmonth := int(now.Month()) nday := now.Day() nhour := now.Hour() nminute := now.Minute() var result []time.Time for i := 1; i <= 12; i++ { if i < nmonth { continue } month := ty.Month[i] if month != nil { for j := 1; j <= 31; j++ { if nmonth == i { if j < nday { // 获取当天的计划表 continue } } day := month.Day[j] if day != nil { if day.IsClear { insertHour(cron, day) // 生成小时的计划表 } for k := 0; k <= 23; k++ { if nmonth == i && nday == j { if k < nhour { continue } } hour := day.Hour[k] // 遍历24小时 生成需要的计划表 if hour != nil { for n := 0; n <= 59; n++ { if nmonth == i && nday == j && nhour == k { if n < nminute { continue } } min := hour.Minute[n] if min != nil { curTime := time.Date(ty.Year, time.Month(i), j, k, n, 0, 0, time.Local) result = append(result, curTime) count-- // 统计完当前需要的计划任务后就结束 if count <= 0 { ty.clearHour() return result } } } } } } } } } ty.clearHour() return result } // FromCrontab 从Crontab生成树 func (ty *trieYear) FromCrontab(cron *Crontab) { // 月的填充 for _, month := range cron.month { left := month.left right := month.right for i := left; i <= right; i += month.per { curMonth := newMonthNode(ty.Year, i) ty.Month[i] = curMonth // 天的填充 insertDay(cron, curMonth) } } } func filterDay(cron *Crontab, curday *dayNode) bool { for _, w := range cron.week { if w.isAll { return false } for n := w.left; n <= w.right; n += w.per { if n == int(curday.Week) { return false } } } return true } func insertDay(cron *Crontab, curMonth *monthNode) { for _, day := range cron.day { left := day.left if left < 0 { left += curMonth.MaxDay + 1 } right := day.right if right < 0 { right += curMonth.MaxDay + 1 } for j := left; j <= right; j += day.per { curMonth.CreateDay(j) curDay := curMonth.Day[j] if filterDay(cron, curDay) { curMonth.Day[j] = nil } else { // insertHour(cron, curDay) } } } } func insertHour(cron *Crontab, curDay *dayNode) { curDay.IsClear = false // 时的填充 for _, hour := range cron.hour { left := hour.left right := hour.right for k := left; k <= right; k += hour.per { curDay.CreateHour(k) curHour := curDay.Hour[k] insertMinute(cron, curHour) } } } func insertMinute(cron *Crontab, curHour *hourNode) { for _, min := range cron.min { left := min.left right := min.right for l := left; l <= right; l += min.per { curHour.CreateMinute(l) } } }