Documentation
¶
Overview ¶
Package cronexpr parses standard 5-field cron expressions ("minute hour day-of-month month day-of-week") and computes the next matching time, in UTC or in a given time zone. It only evaluates schedules; it does not run anything.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NextInLocation ¶
NextInLocation returns the next time schedule matches strictly after after, evaluated on loc's wall clock. Schedule.Next works in UTC only (see its own doc comment); this shifts after's wall-clock fields in loc into UTC fields, asks Next for the next match against those, then reinterprets the result's fields back as loc's wall clock, the same trick internal/deploy.WindowActive already uses for a freeze window's own timezone. Every caller that needs a cron schedule's next occurrence in a specific timezone (not just UTC) should use this instead of duplicating the shift.
Example ¶
package main
import (
"fmt"
"time"
"github.com/GLINCKER/levelrail/kit/cronexpr"
)
func main() {
s, err := cronexpr.Parse("30 9 * * 1-5")
if err != nil {
panic(err)
}
loc := time.FixedZone("UTC+2", 2*60*60)
after := time.Date(2026, 1, 9, 12, 0, 0, 0, time.UTC)
fmt.Println(cronexpr.NextInLocation(s, after, loc).Format(time.RFC3339))
}
Output: 2026-01-12T09:30:00+02:00
Types ¶
type Schedule ¶
type Schedule struct {
// contains filtered or unexported fields
}
Schedule is a parsed, immutable 5-field cron expression, safe for concurrent use by multiple goroutines (every method only reads its own fields, computed once at Parse time).
func Parse ¶
Parse parses a standard 5-field cron expression. Fields are separated by whitespace; each field is one of "*", a single integer, an "a-b" range, or any of those with a "/step" suffix (e.g. "*/15", "10-20/5"), optionally comma-separating multiple such terms in one field (e.g. "1,15,30"). day-of-week accepts 7 as an alias for 0 (Sunday), the common convention several real cron implementations also accept, though this parser does not accept month or day names (JAN, MON, ...): app.yaml's own schedule field is documented purely as a cron expression, and every worked example in this codebase uses numeric fields only, so name support would be untested surface with no current caller.
func (*Schedule) Next ¶
Next returns the earliest minute-aligned UTC time strictly after t that this Schedule matches, or the zero time.Time if no match exists within searchHorizon. Cron fields have no timezone concept of their own; every caller in this codebase (internal/backup.Scheduler) works in UTC exclusively, the same "everything server-side is UTC, a client converts for display" convention store.BackupHistory's own RFC3339-in-UTC timestamps already establish, so t is converted to UTC here rather than accepting an implicit local-time assumption.
Example ¶
package main
import (
"fmt"
"time"
"github.com/GLINCKER/levelrail/kit/cronexpr"
)
func main() {
s, err := cronexpr.Parse("0 3 * * *")
if err != nil {
panic(err)
}
after := time.Date(2026, 1, 10, 12, 0, 0, 0, time.UTC)
fmt.Println(s.Next(after).Format(time.RFC3339))
}
Output: 2026-01-11T03:00:00Z