A zero-dependency Go library for parsing standard 5-field cron
expressions (minute hour day-of-month month day-of-week), producing
human-readable descriptions of a schedule, and computing the next N
times at which a schedule fires.
Built entirely on the Go standard library — no third-party dependencies.
go get github.com/kasapdev/go-cronparse
package main
import (
"fmt"
"time"
"github.com/kasapdev/go-cronparse"
)
func main() {
schedule, err := cronparse.Parse("*/15 9-17 * * 1-5")
if err != nil {
panic(err)
}
fmt.Println(schedule.Describe())
from := time.Date(2024, 1, 15, 10, 7, 0, 0, time.UTC) // a Monday
for _, next := range schedule.NextN(from, 5) {
fmt.Println(next.Format(time.RFC3339))
}
}Parses a standard 5-field cron expression into a Schedule. Each
field supports:
*— any value- a single number, e.g.
5 - a range, e.g.
1-5 - a step, e.g.
*/15or10-30/5 - a comma-separated list of any of the above, e.g.
1,3,5or1-5,10,15-20
Field bounds:
| Field | Range |
|---|---|
| minute | 0-59 |
| hour | 0-23 |
| day-of-month | 1-31 |
| month | 1-12 |
| day-of-week | 0-7 |
Day-of-week alias: both 0 and 7 mean Sunday. 7 is normalized
to 0 during parsing, so 0 0 * * 7 and 0 0 * * 0 are equivalent.
Parse returns a clear, non-nil error for any malformed expression
(wrong number of fields, out-of-range values, malformed ranges/steps,
non-numeric garbage). It never panics on invalid input.
Returns a human-readable English description of the schedule, e.g.:
* * * * *→"Every minute"0 * * * *→"At minute 0 of every hour, every day"0 9 * * 1-5→"At 09:00, on Monday through Friday"*/15 * * * *→"Every 15 minutes, every day"
Returns the next n times, in ascending order, strictly after from
at which the schedule matches. Operates at minute granularity.
Day-of-month / day-of-week semantics: this library follows
standard (Vixie) cron behavior. If both the day-of-month and
day-of-week fields are restricted (i.e. neither is the literal *),
a day matches when either field matches (OR semantics). If only
one of the two fields is restricted, only that field needs to match.
If both are *, every day matches.
For example, 0 0 1 * 1 (midnight on the 1st of the month, or every
Monday) fires on the 1st of every month and on every Monday — not
only when both conditions coincide.
If a schedule is infeasible (e.g. day-of-month 31 combined with
month 2, which never occurs), NextN may return fewer than n
results rather than looping forever.
go test ./...
Tests include table-driven parse validation (valid and malformed
expressions), hand-verified real-world NextN cases (including
month/year rollovers and weekday-skipping schedules), a dedicated test
for the day-of-week 7 → Sunday alias, and Describe() assertions
for common patterns.
MIT — see LICENSE.