Help us shape the future of Go! Take the 2026 Go Developer Survey

cron

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package cron is the occurrence engine behind a deployment's schedule: the reference's 5-field POSIX cron dialect, matched literally against a wall clock in an IANA timezone.

Due, Next and Upcoming share one generator on purpose. The list a user reads in a deployment's upcoming_runs_at and the instant the scheduler actually fires come from the same walk, so they cannot disagree — plan 37 §3.1, and the property test in cron_test.go asserts it.

The dialect is a strict subset of what a general cron library accepts, which is why this is hand-rolled: seconds and year fields, the special characters L, W, # and ?, and predefined shortcuts like @daily are all excluded, so a library would need a rejection layer in front of it and would still not supply the two daylight-saving rules below.

Timezones

The tzdata import is deliberate and belongs here rather than in a main. The server image is debian:stable-slim with ca-certificates and nothing else, so without an embedded database every non-UTC deployment would be refused at create time in the image and never in the test gate, whose host has a zoneinfo tree. Costing ~450 KB in the binary buys the guarantee that no binary or test can forget it.

Daylight saving

A wall clock that does not exist on the spring-forward day is skipped; one that occurs twice on the fall-back day fires twice, as two distinct instants. Neither rule is published by the reference — both are registered inferences (plan 37 §8.1 entry 19) — and both are the highest-risk code here, because a wrong answer looks exactly like a right one.

Index

Constants

View Source
const SearchYears = 12

SearchYears bounds every walk. Twelve rather than a round four because "0 0 29 2 *" — the sparsest satisfiable expression — has an eight-year gap across 2100, which is not a leap year; a shorter bound would report a legal schedule as unsatisfiable (plan 37 §3.3).

Exported because the API refuses an expression with no occurrence inside it and has to say how far it looked: "no occurrence in the next N years" is a message an operator can act on, and "never fires" alone is not.

Variables

View Source
var (
	ErrExpression = errors.New("invalid cron expression")
	ErrTimezone   = errors.New("invalid timezone")
)

ErrExpression and ErrTimezone are distinguishable because the API turns them into 400s naming different fields; a caller must not have to match strings.

Functions

func Due

func Due(expr, timezone string, from, to time.Time) ([]time.Time, error)

Due returns every occurrence in (from, to], ascending. The lower bound is exclusive because the scheduler's watermark is the last occurrence it claimed; including it would re-select that one on every tick.

func Next

func Next(expr, timezone string, after time.Time) (time.Time, bool, error)

Next returns the first occurrence strictly after `after`. The bool is false when the expression has none inside the search bound — which is how an unsatisfiable expression such as "0 0 31 2 *" reports itself, without being an error: it parses, and every field is in range.

func Upcoming

func Upcoming(expr, timezone string, after time.Time, n int) ([]time.Time, error)

Upcoming returns up to n occurrences after `after`, ascending. Fewer than n means the search bound was reached, which for an active deployment is what create and update refuse.

Types

This section is empty.

Jump to

Keyboard shortcuts

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