master
兔子 2 years ago
parent 1cae9d332f
commit c1295d9e26

@ -0,0 +1,22 @@
package startimer
import (
"errors"
"strings"
)
func parseCron(cron string) (StarTimer, error) {
for {
oldLen := len(cron)
cron = strings.ReplaceAll(strings.TrimSpace(cron), " ", " ")
if len(cron) == oldLen {
break
}
}
ct := strings.Split(cron, " ")
if len(ct) != 6 {
return StarTimer{}, errors.New("Invalid cron,argument not enough")
}
return StarTimer{}, nil
}

@ -0,0 +1,7 @@
package startimer
import "testing"
func TestParseCron(t *testing.T) {
parseCron("0 */4 * * * *")
}

@ -7,7 +7,7 @@ import (
) )
func TestTimer(t *testing.T) { func TestTimer(t *testing.T) {
tk:= StarTimer{ tk := StarTimer{
base: time.Now(), base: time.Now(),
repeat: []*Repeats{ repeat: []*Repeats{
{ {
@ -17,6 +17,10 @@ func TestTimer(t *testing.T) {
Unit: STAR_MINUTE, Unit: STAR_MINUTE,
Value: 7, Value: 7,
}, },
{
Unit: STAR_HOUR,
Value: 19,
},
{ {
Unit: STAR_HOUR, Unit: STAR_HOUR,
Value: 18, Value: 18,
@ -47,9 +51,103 @@ func TestTimer(t *testing.T) {
}, },
}, },
} }
base:=tk.base base := tk.base
for i:=0;i<10;i++{ for i := 0; i < 50; i++ {
base=tk.parseNextDate(base) base = tk.parseNextDate(base, true)
fmt.Println(base)
}
}
func TestPrepareCronMax(t *testing.T) {
var rpt = new(Repeats)
for i := 0; i < 60; i++ {
if i%2 != 0 {
continue
}
rpt.Repeat = append(rpt.Repeat, Repeat{
Unit: STAR_SECOND,
Value: uint32(i),
}, Repeat{
Unit: STAR_MINUTE,
Value: uint32(i),
})
}
/*
for i := 0; i < 24; i++ {
rpt.Repeat = append(rpt.Repeat, Repeat{
Unit: STAR_HOUR,
Value: uint32(i),
})
}
*/
for i := 1; i < 7; i++ {
rpt.Repeat = append(rpt.Repeat, Repeat{
Unit: STAR_MONTH,
Value: uint32(i),
})
}
tk := StarTimer{
base: time.Now(),
repeat: []*Repeats{
{
Every: false,
Repeat: rpt.Repeat,
},
},
}
base := tk.base
for i := 0; i < 10; i++ {
base = tk.parseNextDate(base, true)
fmt.Println(base)
}
}
func TestPrepareCron(t *testing.T) {
tk := StarTimer{
base: time.Now(),
repeat: []*Repeats{
{
//*/3,5,6 */2,4,6 6 1-5 5
Every: false,
Repeat: []Repeat{
{Unit: STAR_MINUTE, Value: 0}, {Unit: STAR_MINUTE, Value: 3}, {Unit: STAR_MINUTE, Value: 6}, {Unit: STAR_MINUTE, Value: 9}, {Unit: STAR_MINUTE, Value: 12}, {Unit: STAR_MINUTE, Value: 15}, {Unit: STAR_MINUTE, Value: 18}, {Unit: STAR_MINUTE, Value: 21},
{Unit: STAR_MINUTE, Value: 24}, {Unit: STAR_MINUTE, Value: 27}, {Unit: STAR_MINUTE, Value: 30}, {Unit: STAR_MINUTE, Value: 33}, {Unit: STAR_MINUTE, Value: 36}, {Unit: STAR_MINUTE, Value: 39}, {Unit: STAR_MINUTE, Value: 42}, {Unit: STAR_MINUTE, Value: 45},
{Unit: STAR_MINUTE, Value: 48}, {Unit: STAR_MINUTE, Value: 51}, {Unit: STAR_MINUTE, Value: 54}, {Unit: STAR_MINUTE, Value: 57}, {Unit: STAR_MINUTE, Value: 5},
{Unit: STAR_HOUR, Value: 2}, {Unit: STAR_HOUR, Value: 4}, {Unit: STAR_HOUR, Value: 6}, {Unit: STAR_HOUR, Value: 8}, {Unit: STAR_HOUR, Value: 10}, {Unit: STAR_HOUR, Value: 12}, {Unit: STAR_HOUR, Value: 14}, {Unit: STAR_HOUR, Value: 16}, {Unit: STAR_HOUR, Value: 18}, {Unit: STAR_HOUR, Value: 20}, {Unit: STAR_HOUR, Value: 22}, {Unit: STAR_HOUR, Value: 0},
{Unit: STAR_DAY, Value: 6},
{Unit: STAR_MONTH, Value: 1}, {Unit: STAR_MONTH, Value: 2}, {Unit: STAR_MONTH, Value: 3}, {Unit: STAR_MONTH, Value: 4}, {Unit: STAR_MONTH, Value: 5},
{Unit: STAR_WEEK, Value: 5},
},
},
},
}
base := tk.base
for i := 0; i < 10; i++ {
base = tk.parseNextDate(base, true)
fmt.Println(base)
}
}
func TestPrepareCronSimple(t *testing.T) {
tk := StarTimer{
base: time.Now(),
repeat: []*Repeats{
{
Every: false,
Repeat: []Repeat{
{Unit: STAR_MINUTE, Value: 0}, {Unit: STAR_MINUTE, Value: 3}, {Unit: STAR_MINUTE, Value: 6},
{Unit: STAR_HOUR, Value: 2}, {Unit: STAR_HOUR, Value: 4}, {Unit: STAR_HOUR, Value: 6},
{Unit: STAR_DAY, Value: 6},
{Unit: STAR_MONTH, Value: 1}, {Unit: STAR_MONTH, Value: 5},
},
},
},
}
base := tk.base
for i := 0; i < 1; i++ {
base = tk.parseNextDate(base, true)
fmt.Println(base) fmt.Println(base)
fmt.Println("")
} }
} }

@ -201,9 +201,14 @@ func (t *StarTimer) parseNextDate(base time.Time, isMock bool) time.Time {
if len(dates) == 0 { if len(dates) == 0 {
return time.Time{} return time.Time{}
} }
now := time.Now().UnixNano() var bt int64
if !isMock {
bt = time.Now().UnixNano()
} else {
bt = base.UnixNano()
}
for _, v := range dates { for _, v := range dates {
if v.UnixNano() > now { if v.UnixNano() > bt {
return v return v
} }
} }
@ -211,9 +216,41 @@ func (t *StarTimer) parseNextDate(base time.Time, isMock bool) time.Time {
} }
func (t *StarTimer) parseStaticNextDate(base time.Time, r *Repeats) time.Time { func (t *StarTimer) parseStaticNextDate(base time.Time, r *Repeats) time.Time {
var targets []time.Time
var uniqueRepeat [][]Repeat
selectMap := make(map[Unit][]Repeat)
{
for _, d := range r.Repeat {
selectMap[d.Unit] = append(selectMap[d.Unit], d)
}
for key, val := range selectMap {
if key == STAR_WEEK {
continue
}
defUnikey := make([][]Repeat, 0, 1024)
for _, vs := range val {
if len(uniqueRepeat) == 0 {
defUnikey = append(defUnikey, []Repeat{vs})
} else {
for k := range uniqueRepeat {
tmp := make([]Repeat, len(uniqueRepeat[k])+1)
copy(tmp, append(uniqueRepeat[k], vs))
defUnikey = append(defUnikey, tmp)
}
}
}
if len(defUnikey) > 0 {
uniqueRepeat = defUnikey
}
}
}
for _, task := range uniqueRepeat {
sort.SliceStable(task, func(i, j int) bool {
return task[i].Unit < task[j].Unit
})
target := base target := base
if !r.Every { //固定日期 if !r.Every { //固定日期
for _, d := range r.Repeat { for _, d := range task {
switch d.Unit { switch d.Unit {
case STAR_SECOND: case STAR_SECOND:
sub := int(d.Value) - target.Second() sub := int(d.Value) - target.Second()
@ -249,16 +286,42 @@ func (t *StarTimer) parseStaticNextDate(base time.Time, r *Repeats) time.Time {
case STAR_YEAR: case STAR_YEAR:
sub := int(d.Value) - int(target.Year()) sub := int(d.Value) - int(target.Year())
if sub < 0 { if sub < 0 {
return time.Date(0, 0, 0, 0, 0, 0, 0, nil) continue
} }
target = target.AddDate(sub, 0, 0) target = target.AddDate(sub, 0, 0)
} }
} }
} }
if target == base { if target == base {
return time.Time{} continue
}
targets = append(targets, target)
}
sort.SliceStable(targets, func(i, j int) bool {
return targets[i].UnixNano() < targets[j].UnixNano()
})
for k, v := range targets {
if v.After(base) {
targets = targets[k:]
break
}
}
if val, ok := selectMap[STAR_WEEK]; ok {
if len(targets) > 0 {
for _, week := range val {
if int(targets[0].Weekday()) == int(week.Value) {
return targets[0]
}
} }
return target return t.parseStaticNextDate(targets[0].Add(time.Hour*24), r)
}
}
if len(targets) > 0 {
return targets[0]
}
return time.Time{}
} }
func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats, isMock bool) []time.Time { func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats, isMock bool) []time.Time {

@ -15,6 +15,7 @@ const (
STAR_DAY STAR_DAY
STAR_MONTH STAR_MONTH
STAR_YEAR STAR_YEAR
STAR_WEEK
) )
type Repeats struct { type Repeats struct {

Loading…
Cancel
Save