mirror of https://github.com/shunfei/cronsun
suport at. e.g. "@at 2006-01-02 15:04:05"
parent
baaaa5eef8
commit
b1f93a411c
|
@ -0,0 +1,34 @@
|
||||||
|
package cron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TimeListSchedule will run at the specify giving time.
|
||||||
|
type TimeListSchedule struct {
|
||||||
|
timeList []time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// At returns a crontab Schedule that activates every specify time.
|
||||||
|
func At(tl []time.Time) *TimeListSchedule {
|
||||||
|
sort.Slice(tl, func(i, j int) bool { return tl[i].Unix() < tl[j].Unix() })
|
||||||
|
return &TimeListSchedule{
|
||||||
|
timeList: tl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next time this should be run.
|
||||||
|
// This rounds so that the next activation time will be on the second.
|
||||||
|
func (schedule *TimeListSchedule) Next(t time.Time) time.Time {
|
||||||
|
cur := 0
|
||||||
|
for cur < len(schedule.timeList) {
|
||||||
|
nextt := schedule.timeList[cur]
|
||||||
|
cur++
|
||||||
|
if nextt.UnixNano() <= t.UnixNano() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nextt
|
||||||
|
}
|
||||||
|
return time.Time{}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package cron
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTimeListNext(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
startTime string
|
||||||
|
times []string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
// Simple cases
|
||||||
|
{
|
||||||
|
"2018-09-01 08:01:02",
|
||||||
|
[]string{"2018-09-01 10:01:02"},
|
||||||
|
[]string{"2018-09-01 10:01:02"},
|
||||||
|
},
|
||||||
|
|
||||||
|
// sort list
|
||||||
|
{
|
||||||
|
"2018-09-01 08:01:02",
|
||||||
|
[]string{"2018-09-01 10:01:02", "2018-09-02 10:01:02"},
|
||||||
|
[]string{"2018-09-01 10:01:02", "2018-09-02 10:01:02"},
|
||||||
|
},
|
||||||
|
|
||||||
|
// sort list with middle start time
|
||||||
|
{
|
||||||
|
"2018-09-01 10:11:02",
|
||||||
|
[]string{"2018-09-01 10:01:02", "2018-09-02 10:01:02"},
|
||||||
|
[]string{"2018-09-02 10:01:02"},
|
||||||
|
},
|
||||||
|
|
||||||
|
// unsorted list
|
||||||
|
{
|
||||||
|
"2018-07-01 08:01:02",
|
||||||
|
[]string{"2018-09-01 10:01:00", "2018-08-01 10:00:00", "2018-09-01 10:00:00", "2018-08-02 10:01:02"},
|
||||||
|
[]string{"2018-08-01 10:00:00", "2018-08-02 10:01:02", "2018-09-01 10:00:00", "2018-09-01 10:01:00"},
|
||||||
|
},
|
||||||
|
|
||||||
|
// unsorted list with middle start time
|
||||||
|
{
|
||||||
|
"2018-08-03 12:00:00",
|
||||||
|
[]string{"2018-09-01 10:01:00", "2018-08-01 10:00:00", "2018-09-01 10:00:00", "2018-08-02 10:01:02"},
|
||||||
|
[]string{"2018-09-01 10:00:00", "2018-09-01 10:01:00"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range tests {
|
||||||
|
tls := At(getAtTimes(c.times))
|
||||||
|
nextTime := getAtTime(c.startTime)
|
||||||
|
for _, trun := range c.expected {
|
||||||
|
actual := tls.Next(nextTime)
|
||||||
|
expected := getAtTime(trun)
|
||||||
|
if actual != expected {
|
||||||
|
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)",
|
||||||
|
c.startTime, c.times, expected, actual)
|
||||||
|
}
|
||||||
|
nextTime = actual
|
||||||
|
}
|
||||||
|
if actual := tls.Next(nextTime); !actual.IsZero() {
|
||||||
|
t.Errorf("%s, \"%s\": next time should be zero, but got %v (actual)",
|
||||||
|
c.startTime, c.times, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAtTime(value string) time.Time {
|
||||||
|
if value == "" {
|
||||||
|
panic("time string is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := time.Parse("2006-01-02 15:04:05", value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAtTimes(values []string) []time.Time {
|
||||||
|
tl := []time.Time{}
|
||||||
|
for _, v := range values {
|
||||||
|
tl = append(tl, getAtTime(v))
|
||||||
|
}
|
||||||
|
return tl
|
||||||
|
}
|
|
@ -373,5 +373,21 @@ func parseDescriptor(descriptor string) (Schedule, error) {
|
||||||
return Every(duration), nil
|
return Every(duration), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const at = "@at "
|
||||||
|
if strings.HasPrefix(descriptor, at) {
|
||||||
|
tss := strings.Split(descriptor[len(at):], ",")
|
||||||
|
atls := make([]time.Time, 0, len(tss))
|
||||||
|
for _, ts := range tss {
|
||||||
|
ts = strings.TrimSpace(ts)
|
||||||
|
att, err := time.ParseInLocation("2006-01-02 15:04:05", ts, time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to parse time %s: %s", descriptor, err)
|
||||||
|
}
|
||||||
|
atls = append(atls, att)
|
||||||
|
}
|
||||||
|
|
||||||
|
return At(atls), nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("Unrecognized descriptor: %s", descriptor)
|
return nil, fmt.Errorf("Unrecognized descriptor: %s", descriptor)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue