cronexpr

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

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

func NextInLocation(schedule *Schedule, after time.Time, loc *time.Location) time.Time

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

func Parse(expr string) (*Schedule, error)

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

func (s *Schedule) Next(t time.Time) time.Time

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL