Cron
Utilities for recurring calendar schedules written as cron expressions or
explicit field constraints. A Cron value stores allowed seconds, minutes,
hours, days of month, months, weekdays, and an optional time zone. The module
can create or parse schedules, compare them, test whether a date matches, and
find previous or next scheduled occurrences.
Constructors
Creates a Cron instance from time constraints.
When to use
Use to build a cron schedule from explicit sets of allowed time-field values.
Details
Constructs a cron schedule by specifying which seconds, minutes, hours,
days, months, and weekdays the schedule should match. Empty arrays leave a
time unit unrestricted. If only days or weekdays are restricted, that field
must match. When both are restricted, the default matches either field; set
and: true to require both fields to match. Weekdays range from 0 (Sunday)
to 7 (also Sunday). The constructor throws a RangeError when a field
contains a non-integer or out-of-range value.
See
- parse for building a schedule from a cron expression string
Signature
declare function make(values: { readonly and?: boolean; readonly days: Iterable<number>; readonly hours: Iterable<number>; readonly minutes: Iterable<number>; readonly months: Iterable<number>; readonly seconds?: Iterable<number, any, any>; readonly tz?: TimeZone; readonly weekdays: Iterable<number>;}): CronExample
(Creating schedules from constraints)
import { Cron, DateTime } from "effect"
const utc = DateTime.zoneMakeNamedUnsafe("UTC")
// Every day at midnightconst midnight = Cron.make({ minutes: [0], hours: [0], days: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [0, 1, 2, 3, 4, 5, 6], tz: utc})
// Every 15 minutes during business hours on weekdaysconst businessHours = Cron.make({ minutes: [0, 15, 30, 45], hours: [9, 10, 11, 12, 13, 14, 15, 16, 17], days: [], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5], // Monday to Friday tz: utc})
Cron.match(midnight, "2024-01-01T00:00:00Z") // => trueCron.match(businessHours, "2024-01-01T09:15:00Z") // => trueParses a cron expression safely into a Cron instance, returning a Result
instead of throwing.
When to use
Use to parse cron expressions from configuration or user input while handling
invalid input as a Result.
Details
The expression may contain five fields, where seconds default to 0, or six
fields including seconds. Fields support *, comma-separated values, ranges,
steps, and month or weekday aliases. Invalid expressions fail with
CronParseError. When both the day-of-month and weekday fields are
restricted, a date matches if either field matches. When either field starts
with *, both fields must match; an unrestricted field always matches.
See
- parseUnsafe for throwing on invalid cron expressions
- make for constructing a schedule from explicit field constraints
Signature
declare function parse(cron: string, tz?: string | TimeZone): Result<Cron, CronParseError>Example
(Parsing cron expressions)
import { Cron, Result } from "effect"
// At 04:00 on every day-of-month from 8 through 14.const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *"))
Array.from(cron.hours) // => [4]Array.from(cron.days) // => [8, 9, 10, 11, 12, 13, 14]parseUnsafe
Parses a cron expression into a Cron instance, throwing on failure.
When to use
Use when you expect the input to be valid and want to avoid handling the
Result type.
Signature
declare function parseUnsafe(cron: string, tz?: string | TimeZone): CronExample
(Parsing cron expressions unsafely)
import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14const cron = Cron.parseUnsafe("0 0 4 8-14 * *", "UTC")
// With timezoneconst cronWithTz = Cron.parseUnsafe("0 0 9 * * *", "America/New_York")
// This would throw an error// const invalid = Cron.parseUnsafe("invalid expression")Cron.match(cron, "2024-01-10T04:00:00Z") // => trueCron.match(cronWithTz, "2024-01-01T14:00:00Z") // => trueErrors
CronParseError
Represents an error that occurs when parsing a cron expression fails.
When to use
Use to handle invalid cron expression failures returned by parse.
Details
This error provides information about what went wrong during parsing, including the error message and optionally the input that caused the error.
See
- parse for the parser that returns this error in
Result.fail - isCronParseError for narrowing unknown values to this error type
Signature
declare class CronParseError extends YieldableError<this> & { readonly _tag: "CronParseError";} & Readonly<{ readonly input?: string; readonly message: string;}> { constructor(args: { readonly input?: string; readonly message: string; }); readonly "~effect/time/Cron/CronParseError": "~effect/time/Cron/CronParseError";}Example
(Handling cron parse failures)
import { Cron, Result } from "effect"
const expected = Result.fail(new Cron.CronParseError({ message: "Invalid number of segments in cron expression", input: "invalid expression"}))
Cron.parse("invalid expression") // => expectedGetters
Formats a Cron instance as a cron expression.
Details
The default seconds field (0) is omitted unless includeSeconds is true.
Other seconds configurations are always included.
Gotchas
Formatting drops the timezone information and the and restriction between
days and weekdays. Parsing the result is therefore not guaranteed to produce
an equivalent schedule.
Signature
declare function format(cron: Cron, options?: { readonly includeSeconds?: boolean;}): stringExample
(Formatting a cron expression)
import { Cron } from "effect"
const cron = Cron.parseUnsafe("23 0-20/2 * * 0", "UTC")
Cron.format(cron) // => "23 0-20/2 * * 0"Cron.format(cron, { includeSeconds: true }) // => "0 23 0-20/2 * * 0"Returns the next scheduled date/time for the given Cron instance.
When to use
Use to find the next occurrence of a cron schedule after a specific date/time or after the current time.
Details
Searches for the next date and time when the cron schedule should trigger, starting after the specified date/time or after the current time when no date is provided.
See
Signature
declare function next(cron: Cron, now?: Input): DateExample
(Finding the next occurrence)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *", "UTC"))
// Get next run after a specific dateCron.next(cron, "2021-01-01T00:00:00Z").toISOString() // => "2021-01-08T04:00:00.000Z"Returns the previous scheduled date/time for the given Cron instance.
When to use
Use to find the most recent occurrence of a cron schedule before a specific date/time or before the current time.
Details
When no date/time is provided, the search starts from the current time.
Gotchas
The search is strict: if the supplied date/time already matches the schedule, the result is the earlier occurrence.
See
- next for finding the next scheduled occurrence
Signature
declare function prev(cron: Cron, now?: Input): DateGuards
Checks whether a given value is a Cron instance.
When to use
Use to narrow an unknown value before treating it as a Cron schedule.
Details
This function is a type guard that determines whether the provided value is a valid Cron instance by checking for the presence of the Cron type identifier.
See
Signature
declare function isCron(u: unknown): u is CronExample
(Checking cron values)
import { Cron } from "effect"
const cron = Cron.make({ minutes: [0], hours: [9], days: [1, 15], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5]})
Cron.isCron(cron) // => trueCron.isCron({}) // => falseCron.isCron("not a cron") // => falseisCronParseError
Checks whether a given value is a CronParseError instance.
When to use
Use to narrow an unknown failure before handling it as a cron parse error.
Details
This function is a type guard that determines whether the provided value is a CronParseError by checking for the presence of the CronParseError type identifier.
See
- CronParseError for the parse error type
- parse for producing
CronParseErrorvalues on invalid input
Signature
declare function isCronParseError(u: unknown): u is CronParseErrorExample
(Checking cron parse errors)
import { Cron, Result } from "effect"
Result.mapError(Cron.parse("invalid cron expression"), Cron.isCronParseError) // => Result.fail(true)Cron.isCronParseError(new Error("regular error")) // => falseCron.isCronParseError("not an error") // => falseInstances
Equivalence
Equivalence instance for comparing the timezone, field restrictions, and
day-matching mode of two Cron schedules.
When to use
Use to compare cron schedules through APIs that accept an equivalence relation.
Details
This comparison checks the optional timezone, the and day-matching mode,
seconds, minutes, hours, days, months, and weekdays.
See
- equals for directly comparing two
Cronvalues
Signature
declare const Equivalence: Equ.Equivalence<Cron>Example
(Comparing schedules with equivalence)
import { Cron } from "effect"
const cron1 = Cron.make({ minutes: [0, 30], hours: [9], days: [1, 15], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5]})
const cron2 = Cron.make({ minutes: [30, 0], // Different order hours: [9], days: [15, 1], // Different order months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5]})
Cron.Equivalence(cron1, cron2) // => trueModels
Represents a cron schedule with time constraints and timezone information.
When to use
Use to represent a recurring calendar schedule that can be matched against dates or used to compute scheduled occurrences.
Details
A Cron instance defines when a scheduled task should run, supporting
seconds, minutes, hours, days, months, and weekday constraints. It also
supports timezone-aware scheduling.
See
Signature
interface Cron extends Pipeable, Equal, Inspectable { readonly "~effect/time/Cron": "~effect/time/Cron"; readonly days: ReadonlySet<number>; readonly hours: ReadonlySet<number>; readonly minutes: ReadonlySet<number>; readonly months: ReadonlySet<number>; readonly seconds: ReadonlySet<number>; readonly tz: Option<TimeZone>; readonly weekdays: ReadonlySet<number>;}Example
(Creating a cron schedule)
import { Cron, DateTime } from "effect"
// Create a cron that runs at 9 AM on weekdaysconst weekdayMorning = Cron.make({ minutes: [0], hours: [9], days: [], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5], // Monday to Friday tz: DateTime.zoneMakeNamedUnsafe("UTC")})
// Check if a date matches the scheduleCron.match(weekdayMorning, "2023-06-05T09:00:00Z") // => truePredicates
Checks whether two Cron instances have equal timezone values, field
restrictions, and day-matching modes.
When to use
Use to directly compare two cron schedules, including their timezones and day-matching modes.
Details
The comparison checks the optional timezone, the and day-matching mode,
seconds, minutes, hours, days, months, and weekdays.
See
- Equivalence for the reusable equivalence instance
Signature
declare const equals: { (that: Cron): (self: Cron) => boolean; (self: Cron, that: Cron): boolean;}Example
(Checking schedule equality)
import { Cron } from "effect"
const cron1 = Cron.make({ minutes: [0], hours: [9], days: [1, 15], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5]})
const cron2 = Cron.make({ minutes: [0], hours: [9], days: [1, 15], months: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], weekdays: [1, 2, 3, 4, 5]})
Cron.equals(cron1, cron2) // => trueCron.equals(cron1)(cron2) // => trueReturns true when a date/time matches a Cron schedule.
When to use
Use to test whether a specific date/time satisfies a cron schedule.
Details
The schedule's timezone determines which calendar fields are read from the
input; the host system's timezone is used when the schedule has no timezone.
Seconds, minutes, hours, and months are checked against their restrictions;
an empty set leaves that field unrestricted. If only days or weekdays is
restricted, that field must match. If both are restricted, either may match
unless the schedule was created with and: true, which requires both to
match.
See
Signature
declare function match(cron: Cron, date: Input): booleanExample
(Matching dates against a schedule)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *", "UTC"))
// Check if specific dates matchCron.match(cron, "2021-01-08T04:00:00Z") // => trueCron.match(cron, "2021-01-08T05:00:00Z") // => falseCron.match(cron, "2021-01-07T04:00:00Z") // => falseSequencing
Returns an infinite iterator that yields dates matching the Cron schedule.
When to use
Use to lazily iterate future occurrences of a cron schedule.
Details
The iterator generates an infinite sequence of dates when the cron schedule should trigger, starting after the specified date/time or after the current time when no date is provided.
See
- next for computing one next occurrence
Signature
declare function sequence(cron: Cron, now?: Input): IterableIterator<Date>Example
(Iterating scheduled occurrences)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 9 * * 1-5", "UTC")) // 9 AM weekdays
// Get first 5 occurrencesconst iterator = Cron.sequence(cron, "2023-01-01T00:00:00Z")const next5 = Array.from({ length: 5 }, () => iterator.next().value.toISOString())const expected = [ "2023-01-02T09:00:00.000Z", "2023-01-03T09:00:00.000Z", "2023-01-04T09:00:00.000Z", "2023-01-05T09:00:00.000Z", "2023-01-06T09:00:00.000Z"]
next5 // => expected