From 4df88d86801db7dea061d1db670a40e8c9f365f9 Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Wed, 5 Dec 2018 04:25:40 +0800 Subject: [PATCH] =?UTF-8?q?TODO:=20crontab=E7=9A=84=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crontab.go | 17 ++- crontab_test.go | 16 ++- trie_test.go | 350 ------------------------------------------------ trie_year.go | 319 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 346 insertions(+), 356 deletions(-) delete mode 100644 trie_test.go create mode 100644 trie_year.go diff --git a/crontab.go b/crontab.go index 3bbdfc1..ea8e26c 100644 --- a/crontab.go +++ b/crontab.go @@ -6,6 +6,7 @@ import ( "regexp" "strconv" "strings" + "time" "github.com/davecgh/go-spew/spew" ) @@ -28,6 +29,11 @@ type Crontab struct { Day []timePointer Month []timePointer Week []timePointer + + WillPlans []time.Time + SkipPlans []time.Time + + YearPlan *TrieYear } // NewCrontab create 一个crontab @@ -53,13 +59,22 @@ func (cron *Crontab) FromString(crontab string) error { cron.Hour = createTimePointer(matches[1], 0, 23, true) cron.Day = createTimePointer(matches[2], 1, 31, false) cron.Month = createTimePointer(matches[3], 1, 12, true) - cron.Week = createTimePointer(matches[4], 1, 7, true) + cron.Week = createTimePointer(matches[4], 0, 6, true) + + cron.CreateYearPlan() default: return errors.New("mathches len != want, check crontab string") } + return nil } +// CreateYearPlan 创建年度计划 +func (cron *Crontab) CreateYearPlan() { + cron.YearPlan = newTrieYear(time.Now().Year()) + cron.YearPlan.FromCrontab(cron) +} + func createTimePointer(min string, llimit, rlimit int, fixedLeftRight bool) []timePointer { var result []timePointer diff --git a/crontab_test.go b/crontab_test.go index ab08a4c..8fe84e9 100644 --- a/crontab_test.go +++ b/crontab_test.go @@ -14,17 +14,23 @@ import ( func TestParseCrontab(t *testing.T) { // crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围 - crontab := "* * * * *" + crontab := "* * * * 6-6" t.Error("") // t.Error(NewCrontab(crontab)) + var s []*TrieYear PrintMemUsage() - log.Println(time.Now().Hour()) + for i := 0; i < 10000; i++ { + ty := newTrieYear(2018) + ty.FromCrontab(NewCrontab(crontab)) + s = append(s, ty) + } - ty := NewTrieYear(2018) - ty.InsertCrontab(NewCrontab(crontab)) - log.Println(len(ty.AllPlanTime(time.Now()))) + ty := newTrieYear(2018) + cron := NewCrontab(crontab) + ty.FromCrontab(cron) + log.Println(ty.GetPlanTime(cron, time.Now(), 10)) // for { diff --git a/trie_test.go b/trie_test.go deleted file mode 100644 index 171a925..0000000 --- a/trie_test.go +++ /dev/null @@ -1,350 +0,0 @@ -package curl2info - -import ( - "time" -) - -type SecondNode int - -type INode interface { - Get() interface{} - Set(value interface{}) - GetStatus() bool - SetStatus(bool) -} - -type TYNode struct { - IsOk bool - Value interface{} -} - -func (min *TYNode) Get() interface{} { - return min.Value -} - -func (min *TYNode) Set(value interface{}) { - min.Value = value -} - -func (min *TYNode) SetStatus(status bool) { - min.IsOk = status -} - -func (min *TYNode) GetStatus() bool { - return min.IsOk -} - -type MinuteNode struct { - TYNode -} - -func NewMinuteNode() *MinuteNode { - return &MinuteNode{} -} - -type HourNode struct { - TYNode - All *MinuteNode - Minute [60]*MinuteNode -} - -func (hour *HourNode) CreateMinute(nminute int) { - min := &MinuteNode{} - min.IsOk = true - hour.Minute[nminute] = min -} - -func NewHourNode() *HourNode { - return &HourNode{} -} - -type DayNode struct { - TYNode - - Week time.Weekday - All *HourNode - Hour [24]*HourNode -} - -func (day *DayNode) CreateHour(nhour int) { - hour := &HourNode{} - hour.IsOk = true - day.Hour[nhour] = hour -} - -func NewDayNode(curday *time.Time) *DayNode { - day := &DayNode{} - - week := curday.Weekday() - day.IsOk = true - day.Week = week - - return day -} - -type MonthNode struct { - TYNode - - MaxDay int - All *DayNode - 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.IsOk = true - Month.First = &First - Month.MaxDay = Month.First.AddDate(0, 1, -1).Day() - return Month -} - -type TrieYear struct { - Year int - All *MonthNode - Month [13]*MonthNode -} - -func (ty *TrieYear) CheckYear() bool { - year := time.Now().Year() - return ty.Year == year -} - -func NewTrieYear(year int) *TrieYear { - ty := TrieYear{} - ty.Year = time.Now().Year() - return &ty -} - -func (ty *TrieYear) AllPlanTime(aftertime time.Time) []time.Time { - - now := aftertime - - var result []time.Time - - for i := 1; i <= 12; i++ { - - if i < int(now.Month()) { - continue - } - - var month *MonthNode - if ty.All != nil { - month = ty.All - } else { - month = ty.Month[i] - } - - if month != nil { - for j := 1; j <= 31; j++ { - - if j < int(now.Day()) { - continue - } - - var day *DayNode - if month.All != nil { - day = month.All - } else { - day = month.Day[j] - } - - if day != nil { - for k := 0; k <= 23; k++ { - - if k < int(now.Hour()) { - continue - } - - var hour *HourNode - if day.All != nil { - hour = day.All - } else { - hour = day.Hour[k] - } - - if hour != nil { - - for n := 0; n <= 59; n++ { - - if n < int(now.Minute()) { - continue - } - - var min *MinuteNode - if hour.All != nil { - min = hour.All - } else { - min = hour.Minute[n] - } - - if min != nil { - if min.IsOk { - result = append(result, time.Date(ty.Year, time.Month(i), j, k, n, 0, 0, time.Local)) - } - } - } - - } - } - } - } - } - } - - return result -} - -func (ty *TrieYear) TimeUp() INode { - now := time.Now() - - // 月 - var month *MonthNode - if ty.All != nil { - month = ty.All - } else { - month = ty.Month[int(now.Month())] - } - - // 天 - if month != nil { - - var day *DayNode - if month.All != nil { - day = month.All - } else { - day = month.Day[now.Day()] - } - - if day != nil { - - // 星期suit - - var hour *HourNode - if day.All != nil { - hour = day.All - } else { - hour = day.Hour[now.Hour()] - } - - var min *MinuteNode - if hour != nil { - min = hour.Minute[now.Minute()] - } - - return min - } - - } - - return nil -} - -func (ty *TrieYear) InsertCrontab(cron *Crontab) { - // 月的填充 - for _, month := range cron.Month { - - if month.isAll { - ty.All = NewMonthNode(ty.Year, 1) - insertDay(cron, ty.All) - } else { - - 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 true - } - - for n := w.left; n <= w.right; n += w.per { - if time.Weekday(n) == curday.Week { - return true - } - } - } - return false -} - -func insertDay(cron *Crontab, curMonth *MonthNode) { - for _, day := range cron.Day { - if day.isAll { - curMonth.All = NewDayNode(curMonth.First) - insertHour(cron, curMonth.All) - } else { - - 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] - - insertHour(cron, curDay) - } - } - } -} - -func insertHour(cron *Crontab, curDay *DayNode) { - // 时的填充 - for _, hour := range cron.Hour { - if hour.isAll { - curDay.All = NewHourNode() - - insertMinute(cron, curDay.All) - } else { - - 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 { - if min.isAll { - curHour.All = NewMinuteNode() - curHour.All.IsOk = true - } else { - left := min.left - right := min.right - - for l := left; l <= right; l += min.per { - curHour.CreateMinute(l) - } - } - } -} diff --git a/trie_year.go b/trie_year.go new file mode 100644 index 0000000..d0b6529 --- /dev/null +++ b/trie_year.go @@ -0,0 +1,319 @@ +package curl2info + +import ( + "time" +) + +var defaultTime = time.Now() + +type SecondNode int + +// type INode interface { +// Get() interface{} +// Set(value interface{}) +// } + +// type TYNode struct { +// Value interface{} +// } + +// func (min *TYNode) Get() interface{} { +// return min.Value +// } + +// func (min *TYNode) Set(value interface{}) { +// min.Value = value +// } + +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(year int) *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] + + 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 + } + + } + } + + } + } + + } + } + } + } + + return result +} + +// Contain 包含 +// func (ty *TrieYear) Contain(now *time.Time) INode { + +// // 月 +// month := ty.Month[int(now.Month())] + +// if month != nil { + +// // 天 +// day := month.Day[now.Day()] + +// if day != nil { + +// var hour *HourNode +// hour = day.Hour[now.Hour()] + +// var min *MinuteNode +// if hour != nil { +// min = hour.Minute[now.Minute()] +// } + +// return min +// } + +// } + +// return nil +// } + +// 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 true + } + } + } + return false +} + +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) + } + + } +}