moving command line utility here
This commit is contained in:
parent
2323c4aca0
commit
ec79af33a8
|
@ -6,7 +6,7 @@ In another project, I decided to use cron expression syntax to encode scheduling
|
|||
|
||||
The time-matching algorithm in this implementation is efficient, it avoids as much as possible to guess the next matching time stamp, a common technique seen in a number of implementations out there.
|
||||
|
||||
There is also a companion command-line utility to evaluate cron time expressions: <https://github.com/gorhill/cronexprdo> (which of course uses this library).
|
||||
There is also a companion command-line utility to evaluate cron time expressions: <https://github.com/gorhill/cronexpr/cronexpr> (which of course uses this library).
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
cronexpr: command-line utility
|
||||
==============================
|
||||
|
||||
A command-line utility written in Go to evaluate cron time expressions.
|
||||
|
||||
It is based on the standalone Go library <https://github.com/gorhill/cronexpr>.
|
||||
|
||||
## Install
|
||||
|
||||
go get github.com/gorhill/cronexpr
|
||||
go install github.com/gorhill/cronexpr
|
||||
|
||||
## Usage
|
||||
|
||||
cronexpr [options] "{cron expression}"
|
||||
|
||||
## Options
|
||||
|
||||
`-l`:
|
||||
|
||||
Go-compliant time layout to use for outputting time value(s), see <http://golang.org/pkg/time/#pkg-constants>.
|
||||
|
||||
Default is `"Mon, 02 Jan 2006 15:04:05 MST"`
|
||||
|
||||
`-n`:
|
||||
|
||||
Number of resulting time values to output.
|
||||
|
||||
Default is 1.
|
||||
|
||||
`-t`:
|
||||
|
||||
Whole or partial RFC3339 time value (i.e. `2006-01-02T15:04:05Z07:00`) against which the cron expression is evaluated. Examples of valid values include (assuming EST time zone):
|
||||
|
||||
`13` = 2013-01-01T00:00:00-05:00
|
||||
`2013` = 2013-01-01T00:00:00-05:00
|
||||
`2013-08` = 2013-08-01T00:00:00-05:00
|
||||
`2013-08-31` = 2013-08-31T00:00:00-05:00
|
||||
`2013-08-31T12` = 2013-08-31T12:00:00-05:00
|
||||
`2013-08-31T12:40` = 2013-08-31T12:40:00-05:00
|
||||
`2013-08-31T12:40:35` = 2013-08-31T12:40:35-05:00
|
||||
`2013-08-31T12:40:35-10:00` = 2013-08-31T12:40:35-10:00
|
||||
|
||||
Default time is current time, and default time zone is local time zone.
|
||||
|
||||
## Examples
|
||||
|
||||
#### Example 1
|
||||
|
||||
Midnight on December 31st of any year.
|
||||
|
||||
Command:
|
||||
|
||||
cronexpr -t="2013-08-31" -n=5 "0 0 31 12 *"
|
||||
|
||||
Output (assuming computer is in EST time zone):
|
||||
|
||||
# "0 0 31 12 *" + "2013-08-31T00:00:00-04:00" =
|
||||
Tue, 31 Dec 2013 00:00:00 EST
|
||||
Wed, 31 Dec 2014 00:00:00 EST
|
||||
Thu, 31 Dec 2015 00:00:00 EST
|
||||
Sat, 31 Dec 2016 00:00:00 EST
|
||||
Sun, 31 Dec 2017 00:00:00 EST
|
||||
|
||||
#### Example 2
|
||||
|
||||
2pm on February 29th of any year.
|
||||
|
||||
Command:
|
||||
|
||||
cronexpr -t=2000 -n=10 "0 14 29 2 *"
|
||||
|
||||
Output (assuming computer is in EST time zone):
|
||||
|
||||
# "0 14 29 2 *" + "2000-01-01T00:00:00-05:00" =
|
||||
Tue, 29 Feb 2000 14:00:00 EST
|
||||
Sun, 29 Feb 2004 14:00:00 EST
|
||||
Fri, 29 Feb 2008 14:00:00 EST
|
||||
Wed, 29 Feb 2012 14:00:00 EST
|
||||
Mon, 29 Feb 2016 14:00:00 EST
|
||||
Sat, 29 Feb 2020 14:00:00 EST
|
||||
Thu, 29 Feb 2024 14:00:00 EST
|
||||
Tue, 29 Feb 2028 14:00:00 EST
|
||||
Sun, 29 Feb 2032 14:00:00 EST
|
||||
Fri, 29 Feb 2036 14:00:00 EST
|
||||
|
||||
#### Example 3
|
||||
|
||||
12pm on the work day closest to the 15th of March and every three month
|
||||
thereafter.
|
||||
|
||||
Command:
|
||||
|
||||
cronexpr -t=2013-09-01 -n=5 "0 12 15W 3/3 *"
|
||||
|
||||
Output (assuming computer is in EST time zone):
|
||||
|
||||
# "0 12 15W 3/3 *" + "2013-09-01T00:00:00-04:00" =
|
||||
Mon, 16 Sep 2013 12:00:00 EDT
|
||||
Mon, 16 Dec 2013 12:00:00 EST
|
||||
Fri, 14 Mar 2014 12:00:00 EDT
|
||||
Mon, 16 Jun 2014 12:00:00 EDT
|
||||
Mon, 15 Sep 2014 12:00:00 EDT
|
||||
|
||||
#### Example 4
|
||||
|
||||
Midnight on the fifth Saturday of any month (twist: not all months have a 5th
|
||||
specific day of week).
|
||||
|
||||
Command:
|
||||
|
||||
cronexpr -t=2013-09-02 -n 5 "0 0 * * 6#5"
|
||||
|
||||
Output (assuming computer is in EST time zone):
|
||||
|
||||
# "0 0 * * 6#5" + "2013-09-02T00:00:00-04:00" =
|
||||
Sat, 30 Nov 2013 00:00:00 EST
|
||||
Sat, 29 Mar 2014 00:00:00 EDT
|
||||
Sat, 31 May 2014 00:00:00 EDT
|
||||
Sat, 30 Aug 2014 00:00:00 EDT
|
||||
Sat, 29 Nov 2014 00:00:00 EST
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*!
|
||||
* Copyright 2013 Raymond Hill
|
||||
*
|
||||
* Project: github.com/gorhill/cronexprdo
|
||||
* File: main.go
|
||||
* Version: 1.0
|
||||
* License: GPL v3 see <https://www.gnu.org/licenses/gpl.html>
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gorhill/cronexpr"
|
||||
)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var (
|
||||
usage = func() {
|
||||
fmt.Fprintf(os.Stderr, "usage:\n %s [options] \"{cron expression}\"\noptions:\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
inTimeStr string
|
||||
outTimeCount uint
|
||||
outTimeLayout string
|
||||
)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
flag.Usage = usage
|
||||
flag.StringVar(&inTimeStr, "t", "", `whole or partial RFC3339 time value (i.e. "2006-01-02T15:04:05Z07:00") against which the cron expression is evaluated, now if not present`)
|
||||
flag.UintVar(&outTimeCount, "n", 1, `number of resulting time values to output`)
|
||||
flag.StringVar(&outTimeLayout, "l", "Mon, 02 Jan 2006 15:04:05 MST", `Go-compliant time layout to use for outputting time value(s), see <http://golang.org/pkg/time/#pkg-constants>`)
|
||||
flag.Parse()
|
||||
|
||||
cronStr := flag.Arg(0)
|
||||
if len(cronStr) == 0 {
|
||||
flag.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
inTime := time.Now()
|
||||
inTimeLayout := ""
|
||||
timeStrLen := len(inTimeStr)
|
||||
if timeStrLen == 2 {
|
||||
inTimeLayout = "06"
|
||||
} else if timeStrLen >= 4 {
|
||||
inTimeLayout += "2006"
|
||||
if timeStrLen >= 7 {
|
||||
inTimeLayout += "-01"
|
||||
if timeStrLen >= 10 {
|
||||
inTimeLayout += "-02"
|
||||
if timeStrLen >= 13 {
|
||||
inTimeLayout += "T15"
|
||||
if timeStrLen >= 16 {
|
||||
inTimeLayout += ":04"
|
||||
if timeStrLen >= 19 {
|
||||
inTimeLayout += ":05"
|
||||
if timeStrLen >= 20 {
|
||||
inTimeLayout += "Z07:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(inTimeLayout) > 0 {
|
||||
// default to local time zone
|
||||
if timeStrLen < 20 {
|
||||
inTime, err = time.ParseInLocation(inTimeLayout, inTimeStr, time.Local)
|
||||
} else {
|
||||
inTime, err = time.Parse(inTimeLayout, inTimeStr)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "# error: unparseable time value: \"%s\"\n", inTimeStr)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
expr, err := cronexpr.Parse(cronStr)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "# %s: %s\n", os.Args[0], err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Anything on the output which starts with '#' can be ignored if the caller
|
||||
// is interested only in the time values. There is only one time
|
||||
// value per line, and they are always in chronological ascending order.
|
||||
fmt.Printf("# \"%s\" + \"%s\" =\n", cronStr, inTime.Format(time.RFC3339))
|
||||
|
||||
if outTimeCount < 1 {
|
||||
outTimeCount = 1
|
||||
}
|
||||
outTimes := expr.NextN(inTime, outTimeCount)
|
||||
for _, outTime := range outTimes {
|
||||
fmt.Println(outTime.Format(outTimeLayout))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue