Cron expressions with time zones.
Parsing and field matching reuse Oban.Cron.Expression, which only answers "does this minute
match". next_after/3 adds the missing "when is the next one": a walk over local calendar
days that skips a whole day when its month, day of month or weekday cannot match, then
lists the matching local times of the days that remain. Granularity is one minute.
Zone rules come from Tzdata (IANA data bundled with the package, no network at run time).
Daylight saving time
The result is always an instant (UTC, whole minute), strictly after the argument.
- An expression that matches every hour (
*in the hour field) follows the real clock. A local time that does not exist (spring forward) cannot fire, and a local time that occurs twice (fall back) fires twice.0 * * * *therefore fires once per real hour across both changes: no duplicate, no gap. - An expression with fixed hours (
30 2 * * *) fires once per local day. When the local time falls in a spring-forward gap, the run happens at the first minute after the gap (as Vixie cron does) instead of being skipped. When it occurs twice, only the first occurrence fires.
Summary
Functions
Does the local wall-clock minute of datetime match? datetime is read as it is, so pass it
already shifted to the schedule's zone.
The first matching minute strictly after after_dt, as a UTC DateTime, for the expression
read in zone. {:error, :no_match} when none exists within eight years (for example
0 0 30 2 *) and {:error, :invalid_timezone} for an unknown zone.
Parses a five-field expression or an @daily-style alias. @reboot is rejected.
True when zone is a time zone of the bundled IANA database.
Types
Functions
@spec matches?(expr(), DateTime.t() | NaiveDateTime.t()) :: boolean()
Does the local wall-clock minute of datetime match? datetime is read as it is, so pass it
already shifted to the schedule's zone.
@spec next_after(expr() | String.t(), DateTime.t(), String.t()) :: {:ok, DateTime.t()} | {:error, :no_match | :invalid_timezone | String.t()}
The first matching minute strictly after after_dt, as a UTC DateTime, for the expression
read in zone. {:error, :no_match} when none exists within eight years (for example
0 0 30 2 *) and {:error, :invalid_timezone} for an unknown zone.
Parses a five-field expression or an @daily-style alias. @reboot is rejected.
True when zone is a time zone of the bundled IANA database.