package curl2info import ( "errors" "fmt" "log" "regexp" "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)) ty := CreateTrieYear(2018) log.Println(ty.Month[2].MaxDay) }