270 lines
4.4 KiB
Go
270 lines
4.4 KiB
Go
|
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]
|
||
|
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|