automata/cron
UNIX 5-field cron stack: parse a cron string, validate it,
normalise it into a fast-evaluation CronPlan, and ask whether a
given ValidDateTime matches or what the next match is. This
module is the user-facing facade; the typed phases live in the
automata/cron/{ast,parser,validator,normalize,evaluator,iterator, next,builder} submodules.
Types
Wrapper error type for next_after_string and other facade helpers
that combine the parse / validate phases into a single call.
Power users that need to distinguish syntactic from semantic problems
can keep using parse / validate directly and receive the
underlying parser.ParseError / validator.ValidationError.
pub type CronError {
ParseError(parser.ParseError)
ValidationError(validator.ValidationError)
}
Constructors
-
ParseError(parser.ParseError) -
ValidationError(validator.ValidationError)
Values
pub fn any() -> validator.Selector
pub fn at(value value: Int) -> validator.Selector
pub fn between(
from start: Int,
to end: Int,
) -> validator.Selector
pub fn build(
builder builder: builder.Builder,
) -> Result(validator.ValidCron, validator.ValidationError)
pub fn builder() -> builder.Builder
pub fn every(step step: Int) -> validator.Selector
pub fn every_between(
from start: Int,
to end: Int,
step step: Int,
) -> validator.Selector
pub fn every_from(
start start: Int,
step step: Int,
) -> validator.Selector
pub fn item_exact(value value: Int) -> validator.Item
Build an Item matching a single value (for use inside one_of).
pub fn item_range(from start: Int, to end: Int) -> validator.Item
Build an Item matching every value in [from, to] inclusive.
pub fn item_step_any(step step: Int) -> validator.Item
Build an Item of the form */step (every step-th value across
the field’s full range).
pub fn item_step_between(
from start: Int,
to end: Int,
step step: Int,
) -> validator.Item
Build an Item of the form from-to/step.
pub fn item_step_from(
start start: Int,
step step: Int,
) -> validator.Item
Build an Item of the form start/step.
pub fn iterator_after(
spec spec: validator.ValidCron,
boundary boundary: ast.Boundary,
) -> iterator.CronIterator
pub fn iterator_after_plan(
plan plan: normalize.CronPlan,
boundary boundary: ast.Boundary,
) -> iterator.CronIterator
Plan-reuse counterpart to iterator_after/2.
pub fn matches(
spec spec: validator.ValidCron,
at at: ast.ValidDateTime,
) -> Bool
pub fn matches_plan(
plan plan: normalize.CronPlan,
at at: ast.ValidDateTime,
) -> Bool
Same as matches/2 but takes an already-normalized CronPlan,
so callers that evaluate the same spec many times can pay the
normalisation cost once.
pub fn next_after(
spec spec: validator.ValidCron,
after after: ast.ValidDateTime,
) -> option.Option(ast.ValidDateTime)
Return the next ValidDateTime after after that the cron spec
fires at, or None when no such occurrence exists.
UNIX cron is non-terminating — every well-formed ValidCron
specification has infinitely many future firings — so for typical
inputs None is unreachable in practice. The Option shape
is preserved for two narrow cases:
- Internal recursion guard. The next-firing search bounds itself at ~5,000,000 candidate steps (≈ 9.5 years of minute granularity) so a misbehaving plan cannot loop forever. A sufficiently pathological combination of selectors that has no firing within that horizon is treated as “no next occurrence”.
- The maximum representable
ValidDateTimeboundary. If the search would have to advance past the calendar’s representable range to find the next firing, it returnsNonerather than fabricating a value.
Callers that compose next_after into a pipeline can safely treat
None as “no next time” without distinguishing the two reasons —
both are degenerate cases that should never be reached for cron
specs that came out of validate. RRULE’s next_after returns
Option for a different reason (a COUNT=N rule legitimately
exhausts); the cron variant has no such terminating clause.
pub fn next_after_plan(
plan plan: normalize.CronPlan,
after after: ast.ValidDateTime,
) -> option.Option(ast.ValidDateTime)
Plan-reuse counterpart to next_after/2. Same None semantics:
see the next_after/2 doc-comment for the (very narrow) cases
where this can return None for a ValidCron that came out of
validate.
pub fn next_after_string(
expr expr: String,
at at: ast.ValidDateTime,
) -> Result(option.Option(ast.ValidDateTime), CronError)
Parse, validate, and call next_after/2 in a single step.
Equivalent to:
use raw <- result.try(cron.parse(expr) |> result.map_error(ParseError))
use spec <- result.try(cron.validate(raw) |> result.map_error(ValidationError))
Ok(cron.next_after(spec, after: at))
Useful when the caller already holds a cron expression as a string
and a ValidDateTime and just wants the next firing — the common
“from a literal” path. Callers that evaluate the same expression
many times should keep using parse / validate / normalize
and the *_plan family to pay those costs once.
The Option in the success case has the same semantics as
next_after/2; see that function’s doc-comment for the (very
narrow) cases where it can be None.
pub fn normalize(
spec spec: validator.ValidCron,
) -> normalize.CronPlan
Pre-compute the lookup tables evaluator/iterator/next need.
Reuse the resulting CronPlan across calls if you evaluate the
same spec many times — see the *_plan variants.
pub fn one_of(
items items: List(validator.Item),
) -> validator.Selector
pub fn parse(
input input: String,
) -> Result(ast.RawCron, parser.ParseError)
Parse a UNIX 5-field cron expression (minute hour day-of-month month day-of-week) into a RawCron AST. Returns a ParseError
for syntactic problems such as wrong field count or empty fields.
Range and alias validation is done separately by validate/1.
pub fn to_string(spec spec: validator.ValidCron) -> String
Render a ValidCron back to its canonical 5-field string form.
pub fn validate(
raw raw: ast.RawCron,
) -> Result(validator.ValidCron, validator.ValidationError)
Validate a RawCron and return a ValidCron (opaque) when every
field is in range and consistent. The returned value is the only
shape the rest of the pipeline accepts.
pub fn with_day_of_month(
builder: builder.Builder,
day_of_month: validator.Selector,
) -> builder.Builder
pub fn with_day_of_week(
builder: builder.Builder,
day_of_week: validator.Selector,
) -> builder.Builder
pub fn with_hour(
builder: builder.Builder,
hour: validator.Selector,
) -> builder.Builder
pub fn with_minute(
builder: builder.Builder,
minute: validator.Selector,
) -> builder.Builder
pub fn with_month(
builder: builder.Builder,
month: validator.Selector,
) -> builder.Builder