src/metronome/timers

Schedule by Timer

This optional module implements systemd-style OnCalendar expressions. Importing it also imports Metronome's embedded IANA timezone database; an application importing only metronome does not include either feature.

The calendar shape is::

[DayOfWeek] Year-Month-Day Hour:Minute:Second[.Microseconds] [TimeZone]

For example::

import metronome
import metronome/timers

scheduler nightly:
  timer(
    onCalendar="*-*-* 02:00:00 Europe/Amsterdam",
    async=true
  ):
    echo "Running at 02:00 in Amsterdam"

Calendar deadlines are calculated to one microsecond. Metronome uses a millisecond event-loop wait, however, so dispatch is best-effort and is not a real-time guarantee. Nonexistent local times are skipped at DST gaps; ambiguous local times select the earlier occurrence.

Calendar fields accept *, lists separated by commas, ascending .. ranges, and / repetitions with an explicit start value. An optional English weekday prefix is combined with the date using AND semantics. The date also accepts systemd's ~ last-day form. Supported shorthands are minutely, hourly, daily, monthly, weekly, yearly, annually, quarterly, and semiannually.

The timezone suffix may be UTC or an exact name from Metronome's embedded IANA catalog. If omitted, the timezone of the DateTime passed to getNext is used. The next result is returned in that caller timezone.

This module intentionally does not parse complete systemd .timer units and does not implement AccuracySec, persistent catch-up, randomized delay, monotonic boot timers, or wake-from-suspend.

Types

CalendarTimer = object

Procs

proc getNext(timer: CalendarTimer; current: DateTime): Option[DateTime] {.
    ...gcsafe, raises: [], tags: [], forbids: [].}

Return the first matching instant strictly later than current.

When multiple expressions match the same instant, it is returned once.

proc initTimerBeater(timer: CalendarTimer; asyncProc: BeaterAsyncProc;
                     startTime: Option[DateTime] = none(DateTime);
                     endTime: Option[DateTime] = none(DateTime);
                     id: string = ""; throttleNum: int = 1;
                     errorHandler: JobErrorHandler = nil): Beater {.
    ...raises: [ValueError], tags: [TimeEffect], forbids: [].}
Initialize an async beater driven by a parsed calendar timer.
proc initTimerBeater(timer: CalendarTimer; threadProc: BeaterThreadProc;
                     startTime: Option[DateTime] = none(DateTime);
                     endTime: Option[DateTime] = none(DateTime);
                     id: string = ""; throttleNum: int = 1;
                     errorHandler: JobErrorHandler = nil): Beater {.
    ...raises: [ValueError], tags: [TimeEffect], forbids: [].}
Initialize a thread-backed beater driven by a parsed calendar timer.
proc newTimer(onCalendar: openArray[string]): CalendarTimer {.
    ...raises: [ValueError, Exception], tags: [RootEffect], forbids: [].}
Parse repeated OnCalendar expressions into one timer.
proc newTimer(onCalendar: string): CalendarTimer {.
    ...raises: [ValueError, Exception], tags: [RootEffect], forbids: [].}
Parse one systemd-style OnCalendar expression.