master
兔子 1 year 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,16 +7,20 @@ import (
)
func TestTimer(t *testing.T) {
tk:= StarTimer{
base: time.Now(),
repeat: []*Repeats{
tk := StarTimer{
base: time.Now(),
repeat: []*Repeats{
{
Every: false,
Every: false,
Repeat: []Repeat{
{
Unit: STAR_MINUTE,
Value: 7,
},
{
Unit: STAR_HOUR,
Value: 19,
},
{
Unit: STAR_HOUR,
Value: 18,
@ -24,7 +28,7 @@ func TestTimer(t *testing.T) {
},
},
{
Every: false,
Every: false,
Repeat: []Repeat{
{
Unit: STAR_MINUTE,
@ -37,7 +41,7 @@ func TestTimer(t *testing.T) {
},
},
{
Every: true,
Every: true,
Repeat: []Repeat{
{
Unit: STAR_HOUR,
@ -47,9 +51,103 @@ func TestTimer(t *testing.T) {
},
},
}
base:=tk.base
for i:=0;i<10;i++{
base=tk.parseNextDate(base)
base := tk.base
for i := 0; i < 50; i++ {
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("")
}
}

@ -201,9 +201,14 @@ func (t *StarTimer) parseNextDate(base time.Time, isMock bool) time.Time {
if len(dates) == 0 {
return time.Time{}
}
now := time.Now().UnixNano()
var bt int64
if !isMock {
bt = time.Now().UnixNano()
} else {
bt = base.UnixNano()
}
for _, v := range dates {
if v.UnixNano() > now {
if v.UnixNano() > bt {
return v
}
}
@ -211,54 +216,112 @@ func (t *StarTimer) parseNextDate(base time.Time, isMock bool) time.Time {
}
func (t *StarTimer) parseStaticNextDate(base time.Time, r *Repeats) time.Time {
target := base
if !r.Every { //固定日期
var targets []time.Time
var uniqueRepeat [][]Repeat
selectMap := make(map[Unit][]Repeat)
{
for _, d := range r.Repeat {
switch d.Unit {
case STAR_SECOND:
sub := int(d.Value) - target.Second()
if sub < 0 {
sub += 60
}
target = target.Add(time.Second * time.Duration(sub))
case STAR_MINUTE:
sub := int(d.Value) - target.Minute()
if sub < 0 {
sub += 60
}
target = target.Add(time.Minute * time.Duration(sub))
case STAR_HOUR:
sub := int(d.Value) - target.Hour()
if sub < 0 {
sub += 24
}
target = target.Add(time.Hour * time.Duration(sub))
case STAR_DAY:
sub := int(d.Value) - target.Day()
if sub >= 0 {
target = target.Add(time.Hour * 24 * time.Duration(sub))
continue
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)
}
}
target = time.Date(target.Year(), target.Month()+1, int(d.Value), target.Hour(), target.Minute(), target.Second(), 0, target.Location())
case STAR_MONTH:
sub := int(d.Value) - int(target.Month())
if sub < 0 {
sub += 12
}
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
if !r.Every { //固定日期
for _, d := range task {
switch d.Unit {
case STAR_SECOND:
sub := int(d.Value) - target.Second()
if sub < 0 {
sub += 60
}
target = target.Add(time.Second * time.Duration(sub))
case STAR_MINUTE:
sub := int(d.Value) - target.Minute()
if sub < 0 {
sub += 60
}
target = target.Add(time.Minute * time.Duration(sub))
case STAR_HOUR:
sub := int(d.Value) - target.Hour()
if sub < 0 {
sub += 24
}
target = target.Add(time.Hour * time.Duration(sub))
case STAR_DAY:
sub := int(d.Value) - target.Day()
if sub >= 0 {
target = target.Add(time.Hour * 24 * time.Duration(sub))
continue
}
target = time.Date(target.Year(), target.Month()+1, int(d.Value), target.Hour(), target.Minute(), target.Second(), 0, target.Location())
case STAR_MONTH:
sub := int(d.Value) - int(target.Month())
if sub < 0 {
sub += 12
}
target = target.AddDate(0, sub, 0)
case STAR_YEAR:
sub := int(d.Value) - int(target.Year())
if sub < 0 {
continue
}
target = target.AddDate(sub, 0, 0)
}
target = target.AddDate(0, sub, 0)
case STAR_YEAR:
sub := int(d.Value) - int(target.Year())
if sub < 0 {
return time.Date(0, 0, 0, 0, 0, 0, 0, nil)
}
}
if target == base {
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]
}
target = target.AddDate(sub, 0, 0)
}
return t.parseStaticNextDate(targets[0].Add(time.Hour*24), r)
}
}
if target == base {
return time.Time{}
if len(targets) > 0 {
return targets[0]
}
return target
return time.Time{}
}
func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats, isMock bool) []time.Time {

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

Loading…
Cancel
Save