AllPlans error TODO: fixed great trieyear

This commit is contained in:
huangsimin 2018-12-04 20:00:30 +08:00
parent a4b2a61e2c
commit 2edb74f0e4
3 changed files with 464 additions and 248 deletions

View File

@ -1 +1,149 @@
package curl2info
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/davecgh/go-spew/spew"
)
type timePointer struct {
left, right int
leftlimit, rightlimit int
per int
isAll bool
}
func (tp *timePointer) String() string {
return fmt.Sprintf("left: %d, right: %d, leftlimit: %d, rightlimit: %d, per: %d", tp.left, tp.right, tp.leftlimit, tp.rightlimit, tp.per)
}
// Crontab 的string解析
type Crontab struct {
Min []timePointer
Hour []timePointer
Day []timePointer
Month []timePointer
Week []timePointer
}
// NewCrontab create 一个crontab
func NewCrontab(crontab string) *Crontab {
cron := &Crontab{}
cron.FromString(crontab)
return cron
}
func (cron *Crontab) String() string {
return fmt.Sprintf("min:%s\nhour:%s\nday:%s\nmonth:%s\nweek:%s\n", spew.Sdump(cron.Min), spew.Sdump(cron.Hour), spew.Sdump(cron.Day), spew.Sdump(cron.Month), spew.Sdump(cron.Week))
}
// FromString 解析crontab 的 表达式
func (cron *Crontab) FromString(crontab string) error {
crontab = strings.TrimSpace(crontab)
matches := regexp.MustCompile("[^ ]+").FindAllString(crontab, -1)
mlen := len(matches)
switch mlen {
case 5:
cron.Min = createTimePointer(matches[0], 0, 59, true)
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)
default:
return errors.New("mathches len != want, check crontab string")
}
return nil
}
func createTimePointer(min string, llimit, rlimit int, fixedLeftRight bool) []timePointer {
var result []timePointer
exelist := strings.Split(min, ",")
for _, exe := range exelist {
tp := timePointer{}
takeper := strings.Split(exe, "/") // per
var rangevalue, per string
if len(takeper) == 1 {
rangevalue = exe
per = "1"
} else {
rangevalue = takeper[0]
per = takeper[1]
}
// takeRange
be := strings.Split(rangevalue, "-")
var left, rigth string
switch len(be) {
case 1:
left = be[0]
rigth = be[0]
case 2:
left = be[0]
rigth = be[1]
default:
panic(errors.New("range value is > 2"))
}
if left == "*" {
tp.left = llimit
} else {
ileft, err := strconv.Atoi(strings.Replace(left, "^", "-", -1))
if err != nil {
panic(err)
}
tp.left = ileft
}
if rigth == "*" {
tp.right = rlimit
} else {
iright, err := strconv.Atoi(strings.Replace(rigth, "^", "-", -1))
if err != nil {
panic(err)
}
tp.right = iright
}
iper, err := strconv.Atoi(per)
if err != nil {
panic(err)
}
tp.per = iper
tp.leftlimit = llimit
tp.rightlimit = rlimit
// 修正左值
leftfixed := tp.left
if leftfixed < 0 {
leftfixed += tp.rightlimit + 1
if fixedLeftRight {
tp.left = leftfixed
}
}
rightfixed := tp.right
if rightfixed < 0 {
rightfixed += tp.rightlimit + 1
if fixedLeftRight {
tp.right = rightfixed
}
}
// 全部符合 当左等于左 且 右等于右最大 并且 per == 1 TODO: 如果加入时间间隔 就需要 加多一个 附加值
if leftfixed == tp.leftlimit && rightfixed == tp.rightlimit && tp.per == 1 {
tp.isAll = true
}
result = append(result, tp)
}
return result
}

View File

@ -1,244 +1,52 @@
package curl2info
import (
"errors"
"fmt"
"regexp"
"log"
"runtime"
"strconv"
"strings"
"testing"
"time"
"github.com/davecgh/go-spew/spew"
)
// type LRValue struct {
// left, right int
// }
type TimePointer struct {
left, right int
leftlimit, rightlimit int
per int
isAll bool
}
func (tp *TimePointer) String() string {
return fmt.Sprintf("left: %d, right: %d, leftlimit: %d, rightlimit: %d, per: %d", tp.left, tp.right, tp.leftlimit, tp.rightlimit, tp.per)
}
type Crontab struct {
Min []TimePointer
Hour []TimePointer
Day []TimePointer
Month []TimePointer
Week []TimePointer
logMissedTime bool
plans []time.Time
}
func NewCrontab(crontab string) *Crontab {
cron := &Crontab{}
cron.FromString(crontab)
return cron
}
func (cron *Crontab) SetMissedLog(missedlog bool) {
cron.logMissedTime = missedlog
}
func countDays(year int, month int) (days int) {
if month != 2 {
if month == 4 || month == 6 || month == 9 || month == 11 {
days = 30
} else {
days = 31
}
} else {
if ((year%4) == 0 && (year%100) != 0) || (year%400) == 0 {
days = 29
} else {
days = 28
}
}
return days
}
func DayAccordWith(day int, now *time.Time, lm *TimePointer) {
// maxday := countDays(now.Year(), int(now.Month()))
// left := lm.left
// if left < 0 {
// left = maxday + left
// }
// right := lm.right
// if right < 0 {
// right = maxday + right
// }
// if lm.left <= lm.right {
// switch {
// case day < lm.left:
// return &LRValue{lm.left, lm.right}, nil
// case day > lm.right:
// return nil, nil
// case lm.left <= day && day <= lm.right:
// return &LRValue{day, lm.right}, nil
// }
// }
// return nil, fmt.Errorf("day left > right? left: %d, right: %d", lm.left, lm.right)
}
func MonthAccordWith(month int, lm *TimePointer) {
// if lm.left <= lm.right {
// switch {
// case month < lm.left:
// return &LRValue{lm.left, lm.right}, nil
// case month > lm.right:
// return nil, nil
// case lm.left <= month && month <= lm.right:
// return &LRValue{month, lm.right}, nil
// }
// }
//maxday := countDays(now.Year(), month)
// 1-12月
// left := lm.left
// if left < 0 {
// left = maxday + left
// }
// right := lm.right
// if right < 0 {
// right = maxday + right
// }
// if left <= right {
// switch {
// case day < lm.left:
// return &LRValue{lm.left, lm.right}, nil
// case month > lm.right:
// return nil, nil
// case lm.left <= month && month <= lm.right:
// return &LRValue{month, lm.right}, nil
// }
// }
}
func (cron *Crontab) TimeUp() bool {
return false
}
func (cron *Crontab) String() string {
return fmt.Sprintf("min:%s\nhour:%s\nday:%s\nmonth:%s\nweek:%s\n", spew.Sdump(cron.Min), spew.Sdump(cron.Hour), spew.Sdump(cron.Day), spew.Sdump(cron.Month), spew.Sdump(cron.Week))
}
func (cron *Crontab) FromString(crontab string) error {
crontab = strings.TrimSpace(crontab)
matches := regexp.MustCompile("[^ ]+").FindAllString(crontab, -1)
mlen := len(matches)
switch mlen {
case 5:
cron.Min = createTimePointer(matches[0], 0, 59)
cron.Hour = createTimePointer(matches[1], 0, 23)
cron.Day = createTimePointer(matches[2], 1, 31)
cron.Month = createTimePointer(matches[3], 1, 12)
cron.Week = createTimePointer(matches[4], 1, 7)
default:
return errors.New("mathches len != 5, check crontab string")
}
return nil
}
func createTimePointer(min string, llimit, rlimit int) []TimePointer {
var result []TimePointer
exelist := strings.Split(min, ",")
for _, exe := range exelist {
tp := TimePointer{}
takeper := strings.Split(exe, "/") // per
var rangevalue, per string
if len(takeper) == 1 {
rangevalue = exe
per = "0"
} else {
rangevalue = takeper[0]
per = takeper[1]
}
// takeRange
be := strings.Split(rangevalue, "-")
var left, rigth string
switch len(be) {
case 1:
left = be[0]
rigth = be[0]
case 2:
left = be[0]
rigth = be[1]
default:
panic(errors.New("range value is > 2"))
}
if left == "*" {
tp.left = llimit
tp.isAll = true
} else {
ileft, err := strconv.Atoi(strings.Replace(left, "^", "-", -1))
if err != nil {
panic(err)
}
tp.left = ileft
}
if rigth == "*" {
tp.right = rlimit
tp.isAll = true
} else {
iright, err := strconv.Atoi(strings.Replace(rigth, "^", "-", -1))
if err != nil {
panic(err)
}
tp.right = iright
}
iper, err := strconv.Atoi(per)
if err != nil {
panic(err)
}
tp.per = iper
tp.leftlimit = llimit
tp.rightlimit = rlimit
result = append(result, tp)
}
return result
}
func TestParseCrontab(t *testing.T) {
crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围
t.Error(NewCrontab(crontab))
// crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围
crontab := "* * * * *"
t.Error("")
// t.Error(NewCrontab(crontab))
PrintMemUsage()
ty := CreateTrieYear(2018)
log.Println(time.Now().Hour())
spew.Dump(ty)
ty := NewTrieYear(2018)
ty.InsertCrontab(NewCrontab(crontab))
log.Println(len(ty.AllPlanTime(time.Now())))
// for {
// i := ty.TimeUp()
// if i != nil {
// if i.GetStatus() {
// spew.Dump(i)
// log.Println(time.Now())
// break
// }
// }
// time.Sleep(time.Millisecond * 200)
// }
PrintMemUsage()
}
func TestCrontabPlus(t *testing.T) {
// crontab := "0-5/2,7-30/3,30,35,40-^1 * * * *" //(秒) 分 时 号(每月的多少号, 要注意月可可能性) 星期几(每个星期的) /每 ,列表 -范围
// crondata := NewCrontab("*22 * * * *")
}
func PrintMemUsage() {

View File

@ -1,48 +1,92 @@
package curl2info
import "time"
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 {
IsOK bool
// Second [60]SecondNode
TYNode
}
func NewMinuteNode() *MinuteNode {
return &MinuteNode{}
}
type HourNode struct {
IsOK bool
Minute [60]MinuteNode
TYNode
All *MinuteNode
Minute [60]*MinuteNode
}
type DayNode struct {
IsOK bool
Week time.Weekday
Hour [24]*HourNode
func (hour *HourNode) CreateMinute(nminute int) {
min := &MinuteNode{}
min.IsOk = true
hour.Minute[nminute] = min
}
func NewHourNode() *HourNode {
return &HourNode{}
}
func (hour *HourNode) CreateHour(IsOk bool) {
h := &HourNode{}
h.IsOK = IsOk
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.IsOk = true
day.Week = week
return day
}
type MonthNode struct {
IsOK bool
MaxDay int
TYNode
MaxDay int
All *DayNode
First *time.Time
Day [32]*DayNode
}
@ -55,7 +99,7 @@ func (month *MonthNode) CreateDay(nday int) {
func NewMonthNode(year, month int) *MonthNode {
Month := &MonthNode{}
First := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
Month.IsOK = false
Month.IsOk = true
Month.First = &First
Month.MaxDay = Month.First.AddDate(0, 1, -1).Day()
return Month
@ -63,28 +107,244 @@ func NewMonthNode(year, month int) *MonthNode {
type TrieYear struct {
Year int
All *MonthNode
Month [13]*MonthNode
}
func CreateTrieYear(year int) *TrieYear {
func (ty *TrieYear) CheckYear() bool {
year := time.Now().Year()
return ty.Year == year
}
func NewTrieYear(year int) *TrieYear {
ty := TrieYear{}
// ty.Month[0].IsOK = false
for i := 1; i <= 12; i++ {
ty.Month[i] = NewMonthNode(year, i)
month := ty.Month[i]
for begin := 1; begin <= month.MaxDay; begin++ {
month.CreateDay(begin)
for j := 0; j < 24; j++ {
month.Day[begin].Hour[j] = NewHourNode()
}
}
}
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)
}
}
}
}