Cron.ts
Cron.ts overview
Section titled “Cron.ts overview”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.
Since v2.0.0
Exports Grouped by Category
Section titled “Exports Grouped by Category”constructors
Section titled “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 mean “match all” for that time unit.
Example (Creating schedules from constraints)
import { Cron } from "effect"
// 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]})
// 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: [ 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: [1, 2, 3, 4, 5] // Monday to Friday})See
parsefor building a schedule from a cron expression string
Signature
declare const make: (values: { readonly seconds?: Iterable<number> | undefined readonly minutes: Iterable<number> readonly hours: Iterable<number> readonly days: Iterable<number> readonly months: Iterable<number> readonly weekdays: Iterable<number> readonly tz?: DateTime.TimeZone | undefined}) => CronSince v2.0.0
Parses 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.
Example (Parsing cron expressions)
import { Cron, Result } from "effect"import * as assert from "node:assert"
// At 04:00 on every day-of-month from 8 through 14.assert.deepStrictEqual( Cron.parse("0 0 4 8-14 * *"), Result.succeed( Cron.make({ seconds: [0], minutes: [0], hours: [4], days: [8, 9, 10, 11, 12, 13, 14], months: [], weekdays: [] }) ))See
parseUnsafefor throwing on invalid cron expressionsmakefor constructing a schedule from explicit field constraints
Signature
declare const parse: (cron: string, tz?: DateTime.TimeZone | string) => Result.Result<Cron, CronParseError>Since v2.0.0
parseUnsafe
Section titled “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.
Example (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 * *")
// With timezoneconst cronWithTz = Cron.parseUnsafe("0 0 9 * * *", "America/New_York")
// This would throw an error// const invalid = Cron.parseUnsafe("invalid expression")Signature
declare const parseUnsafe: (cron: string, tz?: DateTime.TimeZone | string) => CronSince v4.0.0
getters
Section titled “getters”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.
Example (Finding the next occurrence)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *"))
// Get next run after a specific dateconst after = new Date("2021-01-01T00:00:00Z")const nextRun = Cron.next(cron, after)console.log(nextRun) // 2021-01-08T04:00:00.000Z
// Get next run from current timeconst nextFromNow = Cron.next(cron)console.log(nextFromNow) // Next occurrence from nowSee
prevfor finding the previous scheduled occurrencesequencefor iterating future scheduled occurrences
Signature
declare const next: (cron: Cron, now?: DateTime.DateTime.Input) => DateSince v2.0.0
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
nextfor finding the next scheduled occurrence
Signature
declare const prev: (cron: Cron, now?: DateTime.DateTime.Input) => DateSince v3.20.0
guards
Section titled “guards”isCron
Section titled “isCron”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.
Example (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]})
console.log(Cron.isCron(cron)) // trueconsole.log(Cron.isCron({})) // falseconsole.log(Cron.isCron("not a cron")) // falseSee
makefor constructing aCronvalue directlyparsefor constructing aCronvalue from a string
Signature
declare const isCron: (u: unknown) => u is CronSince v2.0.0
isCronParseError
Section titled “isCronParseError”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.
Example (Checking cron parse errors)
import { Cron, Result } from "effect"
const result = Cron.parse("invalid cron expression")if (Result.isFailure(result)) { const error = result.failure console.log(Cron.isCronParseError(error)) // true}
console.log(Cron.isCronParseError(new Error("regular error"))) // falseconsole.log(Cron.isCronParseError("not an error")) // falseSee
CronParseErrorfor the parse error typeparsefor producingCronParseErrorvalues on invalid input
Signature
declare const isCronParseError: (u: unknown) => u is CronParseErrorSince v4.0.0
instances
Section titled “instances”Equivalence
Section titled “Equivalence”Equivalence instance for comparing the field restrictions of two Cron
schedules.
When to use
Use to compare cron schedules through APIs that accept an equivalence relation.
Details
This comparison checks seconds, minutes, hours, days, months, and weekdays. It does not compare the optional timezone.
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]})
console.log(Cron.Equivalence(cron1, cron2)) // trueSee
equalsfor directly comparing twoCronvalues
Signature
declare const Equivalence: Equ.Equivalence<Cron>Since v2.0.0
models
Section titled “models”Cron (interface)
Section titled “Cron (interface)”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.
Example (Creating a cron schedule)
import { Cron } from "effect"
// Create a cron that runs at 9 AM on weekdaysconst weekdayMorning = Cron.make({ minutes: [0], hours: [9], 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: [1, 2, 3, 4, 5] // Monday to Friday})
// Check if a date matches the scheduleconst matches = Cron.match(weekdayMorning, new Date("2023-06-05T09:00:00"))console.log(matches) // true if it's 9 AM on a weekdaySee
makefor creating a schedule from explicit field constraintsparsefor creating a schedule from a cron expression stringmatchfor testing a date against a schedulenextfor finding the next scheduled occurrence
Signature
export interface Cron extends Pipeable, Equal.Equal, Inspectable { readonly [TypeId]: typeof TypeId readonly tz: Option.Option<DateTime.TimeZone> readonly seconds: ReadonlySet<number> readonly minutes: ReadonlySet<number> readonly hours: ReadonlySet<number> readonly days: ReadonlySet<number> readonly months: ReadonlySet<number> readonly weekdays: ReadonlySet<number> /** @internal */ readonly first: { readonly second: number readonly minute: number readonly hour: number readonly day: number readonly month: number readonly weekday: number } /** @internal */ readonly last: { readonly second: number readonly minute: number readonly hour: number readonly day: number readonly month: number readonly weekday: number } /** @internal */ readonly next: { readonly second: ReadonlyArray<number | undefined> readonly minute: ReadonlyArray<number | undefined> readonly hour: ReadonlyArray<number | undefined> readonly day: ReadonlyArray<number | undefined> readonly month: ReadonlyArray<number | undefined> readonly weekday: ReadonlyArray<number | undefined> } /** @internal */ readonly prev: { readonly second: ReadonlyArray<number | undefined> readonly minute: ReadonlyArray<number | undefined> readonly hour: ReadonlyArray<number | undefined> readonly day: ReadonlyArray<number | undefined> readonly month: ReadonlyArray<number | undefined> readonly weekday: ReadonlyArray<number | undefined> }}Since v2.0.0
CronParseError (class)
Section titled “CronParseError (class)”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.
Example (Handling cron parse failures)
import { Cron, Result } from "effect"
const result = Cron.parse("invalid expression")if (Result.isFailure(result)) { const error: Cron.CronParseError = result.failure console.log(error.message) // "Invalid number of segments in cron expression" console.log(error.input) // "invalid expression"}See
parsefor the parser that returns this error inResult.failisCronParseErrorfor narrowing unknown values to this error type
Signature
declare class CronParseErrorSince v4.0.0
[CronParseErrorTypeId] (property)
Section titled “[CronParseErrorTypeId] (property)”Signature
readonly [CronParseErrorTypeId]: "~effect/time/Cron/CronParseError"predicates
Section titled “predicates”equals
Section titled “equals”Checks whether two Cron instances have the same field restrictions.
When to use
Use to directly compare whether two cron schedules have the same field restrictions.
Details
The comparison checks seconds, minutes, hours, days, months, and weekdays. It does not compare the optional timezone.
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]})
console.log(Cron.equals(cron1, cron2)) // trueconsole.log(Cron.equals(cron1)(cron2)) // true (curried form)See
Equivalencefor the reusable equivalence instance
Signature
declare const equals: { (that: Cron): (self: Cron) => boolean; (self: Cron, that: Cron): boolean }Since v2.0.0
Returns 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
Seconds, minutes, hours, months, and the optional timezone are checked
directly. For day constraints, an empty days or weekdays set means that
field matches every value; when both sets are non-empty, a date matches if
either the day-of-month or weekday matches.
Example (Matching dates against a schedule)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *"))
// Check if specific dates matchconst matches1 = Cron.match(cron, new Date("2021-01-08T04:00:00Z"))console.log(matches1) // true - 4 AM on the 8th
const matches2 = Cron.match(cron, new Date("2021-01-08T05:00:00Z"))console.log(matches2) // false - wrong hour
const matches3 = Cron.match(cron, new Date("2021-01-07T04:00:00Z"))console.log(matches3) // false - wrong daySee
nextfor finding the next matching date/timeprevfor finding the previous matching date/time
Signature
declare const match: (cron: Cron, date: DateTime.DateTime.Input) => booleanSince v2.0.0
sequencing
Section titled “sequencing”sequence
Section titled “sequence”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.
Example (Iterating scheduled occurrences)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 9 * * 1-5")) // 9 AM weekdays
// Get first 5 occurrencesconst iterator = Cron.sequence(cron, new Date("2023-01-01"))const next5 = Array.from({ length: 5 }, () => iterator.next().value)
console.log(next5)// [Mon Jan 02 2023 09:00:00, Tue Jan 03 2023 09:00:00, ...]See
nextfor computing one next occurrence
Signature
declare const sequence: (cron: Cron, now?: DateTime.DateTime.Input) => IterableIterator<Date>Since v2.0.0