crontabex/trie_year.go

270 lines
4.5 KiB
Go
Raw Permalink Normal View History

2018-12-06 03:07:16 +00:00
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 {
2018-12-25 02:17:15 +00:00
if j < nday { // 获取当天的计划表
2018-12-06 03:07:16 +00:00
continue
}
}
day := month.Day[j]
if day != nil {
if day.IsClear {
2018-12-25 02:17:15 +00:00
insertHour(cron, day) // 生成小时的计划表
2018-12-06 03:07:16 +00:00
}
for k := 0; k <= 23; k++ {
if nmonth == i && nday == j {
if k < nhour {
continue
}
}
hour := day.Hour[k]
2018-12-25 02:17:15 +00:00
// 遍历24小时 生成需要的计划表
2018-12-06 03:07:16 +00:00
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)
2018-12-25 02:17:15 +00:00
count-- // 统计完当前需要的计划任务后就结束
2018-12-06 03:07:16 +00:00
if count <= 0 {
ty.clearHour()
return result
}
}
}
}
2018-12-25 02:17:15 +00:00
}
2018-12-06 03:07:16 +00:00
}
}
}
}
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)
}
}
}