TODO: crontab的完善

This commit is contained in:
eson 2018-12-05 04:25:40 +08:00
parent 2edb74f0e4
commit 4df88d8680
4 changed files with 346 additions and 356 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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)
}
}
}
}

319
trie_year.go Normal file
View File

@ -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)
}
}
}