suport at. e.g. "@at 2006-01-02 15:04:05"

pull/109/head
QLeelulu 6 years ago
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
}
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)
}

Loading…
Cancel
Save