changed naming convention as per https://groups.google.com/d/msg/golang-nuts/la6mB5xG1L4/W3aJaIRkZxUJ
This commit is contained in:
parent
ae9c090812
commit
47d3d6e543
58
README.md
58
README.md
|
@ -77,47 +77,32 @@ Import the library:
|
||||||
|
|
||||||
Simplest way:
|
Simplest way:
|
||||||
|
|
||||||
nextTime := cronexpression.NextTime("0 0 29 2 *", time.Now())
|
nextTime := cronexpression.Parse("0 0 29 2 *").Next(time.Now())
|
||||||
|
|
||||||
Assuming `time.Now()` is "2013-08-29 09:28:00", then `nextTime` will be "2016-02-29 00:00:00".
|
Assuming `time.Now()` is "2013-08-29 09:28:00", then `nextTime` will be "2016-02-29 00:00:00".
|
||||||
|
|
||||||
If you need to reuse many times the same cron expression in your code, it is more efficient
|
You can keep the returned Expression pointer around if you want to reuse it:
|
||||||
to create a `CronExpression` object once and keep a copy of it for reuse:
|
|
||||||
|
|
||||||
cronexpr := cronexpression.NewCronExpression("0 0 29 2 *")
|
cronexpr := cronexpression.Parse("0 0 29 2 *")
|
||||||
nextTime := cronexpr.NextTime(time.Now())
|
nextTime := cronexpr.Next(time.Now())
|
||||||
...
|
...
|
||||||
|
nextTime := cronexpr.Next(nextTime)
|
||||||
|
|
||||||
Use `nextTime.IsZero()` to find out whether a valid time was returned. For example,
|
Use `time.IsZero()` to find out whether a valid time was returned. For example,
|
||||||
|
|
||||||
cronexpression.NextTime("* * * * * 1980", time.Now()).IsZero()
|
cronexpression.Next("* * * * * 1980", time.Now()).IsZero()
|
||||||
|
|
||||||
will return `true`, whereas
|
will return `true`, whereas
|
||||||
|
|
||||||
cronexpression.NextTime("* * * * * 2050", time.Now()).IsZero()
|
cronexpression.Next("* * * * * 2050", time.Now()).IsZero()
|
||||||
|
|
||||||
will return `false` (as of 2013-08-29...)
|
will return `false` (as of 2013-08-29...)
|
||||||
|
|
||||||
API
|
You may also query for `n` next time stamps:
|
||||||
---
|
|
||||||
|
|
||||||
#### func NextTime
|
cronexpression.Parse("0 0 29 2 *").NextN(time.Now(), 5)
|
||||||
|
|
||||||
func NextTime(cronLine string, fromTime time.Time) time.Time
|
which returns a slice of time.Time objects, containing the following time stamps (as of 2013-08-30):
|
||||||
|
|
||||||
Given a time stamp `fromTime`, return the closest following time stamp which matches the cron expression string `cronLine`. The `time.Location` of the returned time stamp is the same as `fromTime`.
|
|
||||||
|
|
||||||
#### func NextTimeN
|
|
||||||
|
|
||||||
func NextTimeN(cronLine string, fromTime time.Time, n int) []time.Time
|
|
||||||
|
|
||||||
Given a time stamp `fromTime`, return a slice of `n` closest following time stamps which match the cron expression string `cronLine`. The time stamps in the returned slice are in chronological ascending order. The `time.Location` of the returned time stamps is the same as `fromTime`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
cronexpression.NextTimeN("0 0 0 29 2 ? *", time.Now(), 5)
|
|
||||||
|
|
||||||
will result in the following time stamps being returned (as of 2013-08-30):
|
|
||||||
|
|
||||||
2016-02-29 00:00:00
|
2016-02-29 00:00:00
|
||||||
2020-02-29 00:00:00
|
2020-02-29 00:00:00
|
||||||
|
@ -125,21 +110,6 @@ will result in the following time stamps being returned (as of 2013-08-30):
|
||||||
2028-02-29 00:00:00
|
2028-02-29 00:00:00
|
||||||
2032-02-29 00:00:00
|
2032-02-29 00:00:00
|
||||||
|
|
||||||
#### func NewCronExpression
|
API
|
||||||
|
---
|
||||||
func NewCronExpression(cronLine string) *CronExpression
|
<http://godoc.org/github.com/gorhill/cronexpression>
|
||||||
|
|
||||||
Return a new `CronExpression` pointer which will interpret the cron expression string `cronLine`.
|
|
||||||
|
|
||||||
#### func (*CronExpression) NextTime
|
|
||||||
|
|
||||||
func (cronexpr *CronExpression) NextTime(fromTime time.Time) time.Time
|
|
||||||
|
|
||||||
Given a time stamp `fromTime`, return the closest following time stamp which matches the cron expression `cronexpr`. The `time.Location` of the returned time stamp is the same as `fromTime`.
|
|
||||||
|
|
||||||
#### func (*CronExpression) NextTimeN
|
|
||||||
|
|
||||||
func (cronexpr *CronExpression) NextTimeN(fromTime time.Time, n int) []time.Time
|
|
||||||
|
|
||||||
Given a time stamp `fromTime`, return a slice of `n` closest following time stamps which match the cron expression `cronexpr`. The time stamps in the returned slice are in chronological ascending order. The `time.Location` of the returned time stamps is the same as `fromTime`.
|
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ import (
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// A CronExpression represents a specific cron time expression as defined on
|
// A Expression represents a specific cron time expression as defined on
|
||||||
// Wikipedia: https://en.wikipedia.org/wiki/Cron#CRON_expression
|
// Wikipedia: https://en.wikipedia.org/wiki/Cron#CRON_expression
|
||||||
type CronExpression struct {
|
type Expression struct {
|
||||||
expression string
|
expression string
|
||||||
secondList []int
|
secondList []int
|
||||||
minuteList []int
|
minuteList []int
|
||||||
|
@ -45,10 +45,22 @@ type CronExpression struct {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// NewCronExpression() returns a new CronExpression pointer. It expects
|
// Check whether the cron expression `cronLine` is valid. If not valid, the
|
||||||
|
// index in the `cronLine` string at which there is an error is returned.
|
||||||
|
func Check(cronLine string) int {
|
||||||
|
|
||||||
|
// Split into fields
|
||||||
|
_ = regexp.MustCompile(`\s+`).Split(cronLine, -1)
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Parse() returns a new Expression pointer. It expects
|
||||||
// a well-formed cron expression. If a malformed cron expression is
|
// a well-formed cron expression. If a malformed cron expression is
|
||||||
// supplied, the result is undefined.
|
// supplied, the result is undefined.
|
||||||
func NewCronExpression(cronLine string) *CronExpression {
|
func Parse(cronLine string) *Expression {
|
||||||
cronLineNormalized := cronNormalize(cronLine)
|
cronLineNormalized := cronNormalize(cronLine)
|
||||||
|
|
||||||
// Split into fields
|
// Split into fields
|
||||||
|
@ -76,7 +88,7 @@ func NewCronExpression(cronLine string) *CronExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic parser can be used for most fields
|
// Generic parser can be used for most fields
|
||||||
cronExpr := &CronExpression{
|
cronExpr := &Expression{
|
||||||
expression: cronLine,
|
expression: cronLine,
|
||||||
secondList: genericFieldParse(cronFields[0], 0, 59),
|
secondList: genericFieldParse(cronFields[0], 0, 59),
|
||||||
minuteList: genericFieldParse(cronFields[1], 0, 59),
|
minuteList: genericFieldParse(cronFields[1], 0, 59),
|
||||||
|
@ -97,31 +109,10 @@ func NewCronExpression(cronLine string) *CronExpression {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Given a time stamp `fromTime`, return the closest following time stamp
|
|
||||||
// which matches the cron expression string .. `cronLine`. The `time.Location`
|
|
||||||
// of the returned time stamp is the same as `fromTime`.
|
|
||||||
func NextTime(cronLine string, fromTime time.Time) time.Time {
|
|
||||||
cronexpr := NewCronExpression(cronLine)
|
|
||||||
return cronexpr.NextTime(fromTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Given a time stamp `fromTime`, return a slice of `n` closest following time
|
|
||||||
// stamps which match the cron expression string `cronLine`. The time stamps in
|
|
||||||
// the returned slice are in chronological ascending order. The `time.Location`
|
|
||||||
// of the returned time stamps is the same as `fromTime`.
|
|
||||||
func NextTimeN(cronLine string, fromTime time.Time, n int) []time.Time {
|
|
||||||
cronexpr := NewCronExpression(cronLine)
|
|
||||||
return cronexpr.NextTimeN(fromTime, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// Given a time stamp `fromTime`, return the closest following time stamp which
|
// Given a time stamp `fromTime`, return the closest following time stamp which
|
||||||
// matches the cron expression `cronexpr`. The `time.Location` of the returned
|
// matches the cron expression `cronexpr`. The `time.Location` of the returned
|
||||||
// time stamp is the same as `fromTime`.
|
// time stamp is the same as `fromTime`.
|
||||||
func (cronexpr *CronExpression) NextTime(fromTime time.Time) time.Time {
|
func (cronexpr *Expression) Next(fromTime time.Time) time.Time {
|
||||||
// Special case
|
// Special case
|
||||||
if fromTime.IsZero() {
|
if fromTime.IsZero() {
|
||||||
return fromTime
|
return fromTime
|
||||||
|
@ -207,12 +198,12 @@ func (cronexpr *CronExpression) NextTime(fromTime time.Time) time.Time {
|
||||||
// stamps which match the cron expression `cronexpr`. The time stamps in the
|
// stamps which match the cron expression `cronexpr`. The time stamps in the
|
||||||
// returned slice are in chronological ascending order. The `time.Location` of
|
// returned slice are in chronological ascending order. The `time.Location` of
|
||||||
// the returned time stamps is the same as `fromTime`.
|
// the returned time stamps is the same as `fromTime`.
|
||||||
func (cronexpr *CronExpression) NextTimeN(fromTime time.Time, n int) []time.Time {
|
func (cronexpr *Expression) NextN(fromTime time.Time, n int) []time.Time {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic("CronExpression.NextTimeN(): invalid count")
|
panic("Expression.NextN(): invalid count")
|
||||||
}
|
}
|
||||||
nextTimes := make([]time.Time, 0)
|
nextTimes := make([]time.Time, 0)
|
||||||
fromTime = cronexpr.NextTime(fromTime)
|
fromTime = cronexpr.Next(fromTime)
|
||||||
for {
|
for {
|
||||||
if fromTime.IsZero() {
|
if fromTime.IsZero() {
|
||||||
break
|
break
|
||||||
|
@ -229,7 +220,7 @@ func (cronexpr *CronExpression) NextTimeN(fromTime time.Time, n int) []time.Time
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextYear(t time.Time) time.Time {
|
func (cronexpr *Expression) nextYear(t time.Time) time.Time {
|
||||||
// Find index at which item in list is greater or equal to
|
// Find index at which item in list is greater or equal to
|
||||||
// candidate year
|
// candidate year
|
||||||
i := sort.SearchInts(cronexpr.yearList, t.Year()+1)
|
i := sort.SearchInts(cronexpr.yearList, t.Year()+1)
|
||||||
|
@ -262,7 +253,7 @@ func (cronexpr *CronExpression) nextYear(t time.Time) time.Time {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextMonth(t time.Time) time.Time {
|
func (cronexpr *Expression) nextMonth(t time.Time) time.Time {
|
||||||
// Find index at which item in list is greater or equal to
|
// Find index at which item in list is greater or equal to
|
||||||
// candidate month
|
// candidate month
|
||||||
i := sort.SearchInts(cronexpr.monthList, int(t.Month())+1)
|
i := sort.SearchInts(cronexpr.monthList, int(t.Month())+1)
|
||||||
|
@ -296,7 +287,7 @@ func (cronexpr *CronExpression) nextMonth(t time.Time) time.Time {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) calculateActualDaysOfMonth(year, month int) []int {
|
func (cronexpr *Expression) calculateActualDaysOfMonth(year, month int) []int {
|
||||||
actualDaysOfMonthMap := make(map[int]bool)
|
actualDaysOfMonthMap := make(map[int]bool)
|
||||||
timeOrigin := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
|
timeOrigin := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
|
||||||
lastDayOfMonth := timeOrigin.AddDate(0, 1, -1).Day()
|
lastDayOfMonth := timeOrigin.AddDate(0, 1, -1).Day()
|
||||||
|
@ -382,7 +373,7 @@ func (cronexpr *CronExpression) calculateActualDaysOfMonth(year, month int) []in
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextDayOfMonth(t time.Time) time.Time {
|
func (cronexpr *Expression) nextDayOfMonth(t time.Time) time.Time {
|
||||||
// Find index at which item in list is greater or equal to
|
// Find index at which item in list is greater or equal to
|
||||||
// candidate day of month
|
// candidate day of month
|
||||||
i := sort.SearchInts(cronexpr.actualDaysOfMonthList, t.Day()+1)
|
i := sort.SearchInts(cronexpr.actualDaysOfMonthList, t.Day()+1)
|
||||||
|
@ -403,7 +394,7 @@ func (cronexpr *CronExpression) nextDayOfMonth(t time.Time) time.Time {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextHour(t time.Time) time.Time {
|
func (cronexpr *Expression) nextHour(t time.Time) time.Time {
|
||||||
// Find index at which item in list is greater or equal to
|
// Find index at which item in list is greater or equal to
|
||||||
// candidate hour
|
// candidate hour
|
||||||
i := sort.SearchInts(cronexpr.hourList, t.Hour()+1)
|
i := sort.SearchInts(cronexpr.hourList, t.Hour()+1)
|
||||||
|
@ -424,7 +415,7 @@ func (cronexpr *CronExpression) nextHour(t time.Time) time.Time {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextMinute(t time.Time) time.Time {
|
func (cronexpr *Expression) nextMinute(t time.Time) time.Time {
|
||||||
// Find index at which item in list is greater or equal to
|
// Find index at which item in list is greater or equal to
|
||||||
// candidate minute
|
// candidate minute
|
||||||
i := sort.SearchInts(cronexpr.minuteList, t.Minute()+1)
|
i := sort.SearchInts(cronexpr.minuteList, t.Minute()+1)
|
||||||
|
@ -445,7 +436,7 @@ func (cronexpr *CronExpression) nextMinute(t time.Time) time.Time {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) nextSecond(t time.Time) time.Time {
|
func (cronexpr *Expression) nextSecond(t time.Time) time.Time {
|
||||||
// nextSecond() assumes all other fields are exactly matched
|
// nextSecond() assumes all other fields are exactly matched
|
||||||
// to the cron expression
|
// to the cron expression
|
||||||
|
|
||||||
|
@ -525,7 +516,7 @@ func cronNormalize(cronLine string) string {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) dayofweekFieldParse(cronField string) error {
|
func (cronexpr *Expression) dayofweekFieldParse(cronField string) error {
|
||||||
// Defaults
|
// Defaults
|
||||||
cronexpr.daysOfWeekRestricted = true
|
cronexpr.daysOfWeekRestricted = true
|
||||||
cronexpr.lastWeekDaysOfWeek = make(map[int]bool)
|
cronexpr.lastWeekDaysOfWeek = make(map[int]bool)
|
||||||
|
@ -585,7 +576,7 @@ func (cronexpr *CronExpression) dayofweekFieldParse(cronField string) error {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
func (cronexpr *CronExpression) dayofmonthFieldParse(cronField string) error {
|
func (cronexpr *Expression) dayofmonthFieldParse(cronField string) error {
|
||||||
// Defaults
|
// Defaults
|
||||||
cronexpr.daysOfMonthRestricted = true
|
cronexpr.daysOfMonthRestricted = true
|
||||||
cronexpr.lastDayOfMonth = false
|
cronexpr.lastDayOfMonth = false
|
||||||
|
|
|
@ -109,14 +109,14 @@ var crontests = []crontest{
|
||||||
// TODO: more tests
|
// TODO: more tests
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCronExpressions(t *testing.T) {
|
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)
|
||||||
next := cronexpression.NextTime(test.expr, from)
|
next := cronexpression.Parse(test.expr).Next(from)
|
||||||
nextstr := next.Format(test.layout)
|
nextstr := next.Format(test.layout)
|
||||||
if nextstr != times.next {
|
if nextstr != times.next {
|
||||||
t.Errorf("(\"%s\").NextTime(\"%s\") = \"%s\", got \"%s\"", test.expr, times.from, times.next, nextstr)
|
t.Errorf("(\"%s\").Next(\"%s\") = \"%s\", got \"%s\"", test.expr, times.from, times.next, nextstr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue