Compare commits
No commits in common. "master" and "1.0.0" have entirely different histories.
|
@ -19,7 +19,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -55,7 +54,6 @@ var (
|
||||||
var (
|
var (
|
||||||
numberTokens = map[string]int{
|
numberTokens = map[string]int{
|
||||||
"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
|
"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
|
||||||
"00": 0, "01": 1, "02": 2, "03": 3, "04": 4, "05": 5, "06": 6, "07": 7, "08": 8, "09": 9,
|
|
||||||
"10": 10, "11": 11, "12": 12, "13": 13, "14": 14, "15": 15, "16": 16, "17": 17, "18": 18, "19": 19,
|
"10": 10, "11": 11, "12": 12, "13": 13, "14": 14, "15": 15, "16": 16, "17": 17, "18": 18, "19": 19,
|
||||||
"20": 20, "21": 21, "22": 22, "23": 23, "24": 24, "25": 25, "26": 26, "27": 27, "28": 28, "29": 29,
|
"20": 20, "21": 21, "22": 22, "23": 23, "24": 24, "25": 25, "26": 26, "27": 27, "28": 28, "29": 29,
|
||||||
"30": 30, "31": 31, "32": 32, "33": 33, "34": 34, "35": 35, "36": 36, "37": 37, "38": 38, "39": 39,
|
"30": 30, "31": 31, "32": 32, "33": 33, "34": 34, "35": 35, "36": 36, "37": 37, "38": 38, "39": 39,
|
||||||
|
@ -121,7 +119,7 @@ var (
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 59,
|
max: 59,
|
||||||
defaultList: genericDefaultList[0:60],
|
defaultList: genericDefaultList[0:60],
|
||||||
valuePattern: `0?[0-9]|[1-5][0-9]`,
|
valuePattern: `[0-9]|[1-5][0-9]`,
|
||||||
atoi: atoi,
|
atoi: atoi,
|
||||||
}
|
}
|
||||||
minuteDescriptor = fieldDescriptor{
|
minuteDescriptor = fieldDescriptor{
|
||||||
|
@ -129,7 +127,7 @@ var (
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 59,
|
max: 59,
|
||||||
defaultList: genericDefaultList[0:60],
|
defaultList: genericDefaultList[0:60],
|
||||||
valuePattern: `0?[0-9]|[1-5][0-9]`,
|
valuePattern: `[0-9]|[1-5][0-9]`,
|
||||||
atoi: atoi,
|
atoi: atoi,
|
||||||
}
|
}
|
||||||
hourDescriptor = fieldDescriptor{
|
hourDescriptor = fieldDescriptor{
|
||||||
|
@ -137,7 +135,7 @@ var (
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 23,
|
max: 23,
|
||||||
defaultList: genericDefaultList[0:24],
|
defaultList: genericDefaultList[0:24],
|
||||||
valuePattern: `0?[0-9]|1[0-9]|2[0-3]`,
|
valuePattern: `[0-9]|1[0-9]|2[0-3]`,
|
||||||
atoi: atoi,
|
atoi: atoi,
|
||||||
}
|
}
|
||||||
domDescriptor = fieldDescriptor{
|
domDescriptor = fieldDescriptor{
|
||||||
|
@ -145,7 +143,7 @@ var (
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 31,
|
max: 31,
|
||||||
defaultList: genericDefaultList[1:32],
|
defaultList: genericDefaultList[1:32],
|
||||||
valuePattern: `0?[1-9]|[12][0-9]|3[01]`,
|
valuePattern: `[1-9]|[12][0-9]|3[01]`,
|
||||||
atoi: atoi,
|
atoi: atoi,
|
||||||
}
|
}
|
||||||
monthDescriptor = fieldDescriptor{
|
monthDescriptor = fieldDescriptor{
|
||||||
|
@ -153,7 +151,7 @@ var (
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 12,
|
max: 12,
|
||||||
defaultList: genericDefaultList[1:13],
|
defaultList: genericDefaultList[1:13],
|
||||||
valuePattern: `0?[1-9]|1[012]|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|march|april|june|july|august|september|october|november|december`,
|
valuePattern: `[1-9]|1[012]|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|march|april|june|july|august|september|october|november|december`,
|
||||||
atoi: func(s string) int {
|
atoi: func(s string) int {
|
||||||
return monthTokens[s]
|
return monthTokens[s]
|
||||||
},
|
},
|
||||||
|
@ -163,7 +161,7 @@ var (
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 6,
|
max: 6,
|
||||||
defaultList: genericDefaultList[0:7],
|
defaultList: genericDefaultList[0:7],
|
||||||
valuePattern: `0?[0-7]|sun|mon|tue|wed|thu|fri|sat|sunday|monday|tuesday|wednesday|thursday|friday|saturday`,
|
valuePattern: `[0-7]|sun|mon|tue|wed|thu|fri|sat|sunday|monday|tuesday|wednesday|thursday|friday|saturday`,
|
||||||
atoi: func(s string) int {
|
atoi: func(s string) int {
|
||||||
return dowTokens[s]
|
return dowTokens[s]
|
||||||
},
|
},
|
||||||
|
@ -195,7 +193,6 @@ var (
|
||||||
fieldFinder = regexp.MustCompile(`\S+`)
|
fieldFinder = regexp.MustCompile(`\S+`)
|
||||||
entryFinder = regexp.MustCompile(`[^,]+`)
|
entryFinder = regexp.MustCompile(`[^,]+`)
|
||||||
layoutRegexp = make(map[string]*regexp.Regexp)
|
layoutRegexp = make(map[string]*regexp.Regexp)
|
||||||
layoutRegexpLock sync.Mutex
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -448,9 +445,6 @@ func genericFieldParse(s string, desc fieldDescriptor) ([]*cronDirective, error)
|
||||||
directive.first = desc.min
|
directive.first = desc.min
|
||||||
directive.last = desc.max
|
directive.last = desc.max
|
||||||
directive.step = atoi(snormal[pairs[2]:pairs[3]])
|
directive.step = atoi(snormal[pairs[2]:pairs[3]])
|
||||||
if directive.step < 1 || directive.step > desc.max {
|
|
||||||
return nil, fmt.Errorf("invalid interval %s", snormal)
|
|
||||||
}
|
|
||||||
directives = append(directives, &directive)
|
directives = append(directives, &directive)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -461,9 +455,6 @@ func genericFieldParse(s string, desc fieldDescriptor) ([]*cronDirective, error)
|
||||||
directive.first = desc.atoi(snormal[pairs[2]:pairs[3]])
|
directive.first = desc.atoi(snormal[pairs[2]:pairs[3]])
|
||||||
directive.last = desc.max
|
directive.last = desc.max
|
||||||
directive.step = atoi(snormal[pairs[4]:pairs[5]])
|
directive.step = atoi(snormal[pairs[4]:pairs[5]])
|
||||||
if directive.step < 1 || directive.step > desc.max {
|
|
||||||
return nil, fmt.Errorf("invalid interval %s", snormal)
|
|
||||||
}
|
|
||||||
directives = append(directives, &directive)
|
directives = append(directives, &directive)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -474,9 +465,6 @@ func genericFieldParse(s string, desc fieldDescriptor) ([]*cronDirective, error)
|
||||||
directive.first = desc.atoi(snormal[pairs[2]:pairs[3]])
|
directive.first = desc.atoi(snormal[pairs[2]:pairs[3]])
|
||||||
directive.last = desc.atoi(snormal[pairs[4]:pairs[5]])
|
directive.last = desc.atoi(snormal[pairs[4]:pairs[5]])
|
||||||
directive.step = atoi(snormal[pairs[6]:pairs[7]])
|
directive.step = atoi(snormal[pairs[6]:pairs[7]])
|
||||||
if directive.step < 1 || directive.step > desc.max {
|
|
||||||
return nil, fmt.Errorf("invalid interval %s", snormal)
|
|
||||||
}
|
|
||||||
directives = append(directives, &directive)
|
directives = append(directives, &directive)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -490,9 +478,6 @@ func genericFieldParse(s string, desc fieldDescriptor) ([]*cronDirective, error)
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func makeLayoutRegexp(layout, value string) *regexp.Regexp {
|
func makeLayoutRegexp(layout, value string) *regexp.Regexp {
|
||||||
layoutRegexpLock.Lock()
|
|
||||||
defer layoutRegexpLock.Unlock()
|
|
||||||
|
|
||||||
layout = strings.Replace(layout, `%value%`, value, -1)
|
layout = strings.Replace(layout, `%value%`, value, -1)
|
||||||
re := layoutRegexp[layout]
|
re := layoutRegexp[layout]
|
||||||
if re == nil {
|
if re == nil {
|
||||||
|
|
|
@ -10,13 +10,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cronexpr
|
package cronexpr_test
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorhill/cronexpr"
|
||||||
)
|
)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -201,9 +203,9 @@ func TestExpressions(t *testing.T) {
|
||||||
for _, test := range crontests {
|
for _, test := range crontests {
|
||||||
for _, times := range test.times {
|
for _, times := range test.times {
|
||||||
from, _ := time.Parse("2006-01-02 15:04:05", times.from)
|
from, _ := time.Parse("2006-01-02 15:04:05", times.from)
|
||||||
expr, err := Parse(test.expr)
|
expr, err := cronexpr.Parse(test.expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf(`Parse("%s") returned "%s"`, test.expr, err.Error())
|
t.Errorf(`cronexpr.Parse("%s") returned "%s"`, test.expr, err.Error())
|
||||||
}
|
}
|
||||||
next := expr.Next(from)
|
next := expr.Next(from)
|
||||||
nextstr := next.Format(test.layout)
|
nextstr := next.Format(test.layout)
|
||||||
|
@ -218,17 +220,17 @@ func TestExpressions(t *testing.T) {
|
||||||
|
|
||||||
func TestZero(t *testing.T) {
|
func TestZero(t *testing.T) {
|
||||||
from, _ := time.Parse("2006-01-02", "2013-08-31")
|
from, _ := time.Parse("2006-01-02", "2013-08-31")
|
||||||
next := MustParse("* * * * * 1980").Next(from)
|
next := cronexpr.MustParse("* * * * * 1980").Next(from)
|
||||||
if next.IsZero() == false {
|
if next.IsZero() == false {
|
||||||
t.Error(`("* * * * * 1980").Next("2013-08-31").IsZero() returned 'false', expected 'true'`)
|
t.Error(`("* * * * * 1980").Next("2013-08-31").IsZero() returned 'false', expected 'true'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
next = MustParse("* * * * * 2050").Next(from)
|
next = cronexpr.MustParse("* * * * * 2050").Next(from)
|
||||||
if next.IsZero() == true {
|
if next.IsZero() == true {
|
||||||
t.Error(`("* * * * * 2050").Next("2013-08-31").IsZero() returned 'true', expected 'false'`)
|
t.Error(`("* * * * * 2050").Next("2013-08-31").IsZero() returned 'true', expected 'false'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
next = MustParse("* * * * * 2099").Next(time.Time{})
|
next = cronexpr.MustParse("* * * * * 2099").Next(time.Time{})
|
||||||
if next.IsZero() == false {
|
if next.IsZero() == false {
|
||||||
t.Error(`("* * * * * 2014").Next(time.Time{}).IsZero() returned 'true', expected 'false'`)
|
t.Error(`("* * * * * 2014").Next(time.Time{}).IsZero() returned 'true', expected 'false'`)
|
||||||
}
|
}
|
||||||
|
@ -245,7 +247,7 @@ func TestNextN(t *testing.T) {
|
||||||
"Sat, 29 Nov 2014 00:00:00",
|
"Sat, 29 Nov 2014 00:00:00",
|
||||||
}
|
}
|
||||||
from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:30")
|
from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:30")
|
||||||
result := MustParse("0 0 * * 6#5").NextN(from, uint(len(expected)))
|
result := cronexpr.MustParse("0 0 * * 6#5").NextN(from, uint(len(expected)))
|
||||||
if len(result) != len(expected) {
|
if len(result) != len(expected) {
|
||||||
t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`)
|
t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`)
|
||||||
t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result))
|
t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result))
|
||||||
|
@ -268,7 +270,7 @@ func TestNextN_every5min(t *testing.T) {
|
||||||
"Mon, 2 Sep 2013 09:05:00",
|
"Mon, 2 Sep 2013 09:05:00",
|
||||||
}
|
}
|
||||||
from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:32")
|
from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:32")
|
||||||
result := MustParse("*/5 * * * *").NextN(from, uint(len(expected)))
|
result := cronexpr.MustParse("*/5 * * * *").NextN(from, uint(len(expected)))
|
||||||
if len(result) != len(expected) {
|
if len(result) != len(expected) {
|
||||||
t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
|
t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
|
||||||
t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result))
|
t.Errorf(` Expected %d returned time values but got %d instead`, len(expected), len(result))
|
||||||
|
@ -282,29 +284,6 @@ func TestNextN_every5min(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue: https://github.com/gorhill/cronexpr/issues/16
|
|
||||||
func TestInterval_Interval60Issue(t *testing.T) {
|
|
||||||
_, err := Parse("*/60 * * * * *")
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing with interval 60 should return err")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = Parse("*/61 * * * * *")
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing with interval 61 should return err")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = Parse("2/60 * * * * *")
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing with interval 60 should return err")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = Parse("2-20/61 * * * * *")
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("parsing with interval 60 should return err")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var benchmarkExpressions = []string{
|
var benchmarkExpressions = []string{
|
||||||
|
@ -320,14 +299,14 @@ var benchmarkExpressionsLen = len(benchmarkExpressions)
|
||||||
|
|
||||||
func BenchmarkParse(b *testing.B) {
|
func BenchmarkParse(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_ = MustParse(benchmarkExpressions[i%benchmarkExpressionsLen])
|
_ = cronexpr.MustParse(benchmarkExpressions[i%benchmarkExpressionsLen])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkNext(b *testing.B) {
|
func BenchmarkNext(b *testing.B) {
|
||||||
exprs := make([]*Expression, benchmarkExpressionsLen)
|
exprs := make([]*cronexpr.Expression, benchmarkExpressionsLen)
|
||||||
for i := 0; i < benchmarkExpressionsLen; i++ {
|
for i := 0; i < benchmarkExpressionsLen; i++ {
|
||||||
exprs[i] = MustParse(benchmarkExpressions[i])
|
exprs[i] = cronexpr.MustParse(benchmarkExpressions[i])
|
||||||
}
|
}
|
||||||
from := time.Now()
|
from := time.Now()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
|
@ -8,13 +8,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cronexpr
|
package cronexpr_test
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorhill/cronexpr"
|
||||||
)
|
)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -22,7 +24,7 @@ import (
|
||||||
// ExampleMustParse
|
// ExampleMustParse
|
||||||
func ExampleMustParse() {
|
func ExampleMustParse() {
|
||||||
t := time.Date(2013, time.August, 31, 0, 0, 0, 0, time.UTC)
|
t := time.Date(2013, time.August, 31, 0, 0, 0, 0, time.UTC)
|
||||||
nextTimes := MustParse("0 0 29 2 *").NextN(t, 5)
|
nextTimes := cronexpr.MustParse("0 0 29 2 *").NextN(t, 5)
|
||||||
for i := range nextTimes {
|
for i := range nextTimes {
|
||||||
fmt.Println(nextTimes[i].Format(time.RFC1123))
|
fmt.Println(nextTimes[i].Format(time.RFC1123))
|
||||||
// Output:
|
// Output:
|
||||||
|
|
Loading…
Reference in New Issue