Python API¶
Reference for the dateme Python package.
Exports¶
Top-level package exports:
Name |
Description |
|---|---|
|
Query engine class. |
|
Typed builder module. |
|
Enum values for typed builders. |
|
Date-position builder types. |
|
Overlay builder types. |
|
Calendar spec builder types. |
|
Frequency builder types. |
|
Frequency builder types. |
|
Makeup builder types. |
Schedule¶
Schedule is the Python wrapper around the Rust recurrence engine.
Constructor¶
Schedule(spec, calendar_provider=None)
Parameters:
Parameter |
Type |
Description |
|---|---|---|
|
JSON |
Schedule model. |
|
callable or object, optional |
Provider for |
The constructor validates the schedule. Invalid JSON, invalid enum values,
invalid timezone names, and structural validation failures raise ValueError.
Examples:
from dateme import Schedule
schedule = Schedule({
"freq": {"type": "daily", "time": "09:00"},
"timezone": "UTC",
})
from dateme import Schedule, Weekly, Weekday, Overlay, CalendarId, OverlayRule, Makeup
from dateme import model as m
spec = m.Schedule(
freq=Weekly([Weekday.MON], "17:30"),
timezone="America/New_York",
overlays=[Overlay(CalendarId.NYSE_HOLIDAY, OverlayRule.EXCLUDE)],
makeup=Makeup.AFTER,
)
schedule = Schedule(spec)
Custom Calendar Providers¶
Custom calendars are referenced in a schedule with { "custom": "name" }.
Providers receive (name, date) where date is a YYYY-MM-DD string.
A callable provider:
schedule = Schedule(
{
"freq": {"type": "daily", "time": "09:00"},
"timezone": "UTC",
"overlays": [{"calendar": {"custom": "shutdown"}, "rule": "exclude"}],
},
lambda name, date: name == "shutdown" and date == "2026-08-14",
)
An object provider:
class Calendars:
def contains(self, name: str, date: str) -> bool:
return name == "shutdown" and date in {"2026-08-14", "2026-08-15"}
schedule = Schedule(spec, Calendars())
Missing custom calendar values are treated as absent from the set.
Datetime Handling¶
Rule |
Behavior |
|---|---|
Input datetimes |
Timezone-aware |
Naive inputs |
Interpreted as UTC by PyO3 datetime conversion. |
Returned values |
Timezone-aware UTC |
Optional anchors |
Default to the current UTC time. |
Query bounds |
Strict: occurrences exactly at |
Methods¶
Schedule.from_json¶
Schedule.from_json(json, calendar_provider=None) -> Schedule
Builds a schedule from a JSON string.
schedule = Schedule.from_json('{"freq":{"type":"daily","time":"09:00"},"timezone":"UTC"}')
Schedule.from_dict¶
Schedule.from_dict(spec, calendar_provider=None) -> Schedule
Builds a schedule from a dict or typed builder object.
schedule = Schedule.from_dict({"freq": {"type": "daily", "time": "09:00"}, "timezone": "UTC"})
to_json¶
schedule.to_json() -> str
Returns the JSON representation.
blob = schedule.to_json()
again = Schedule.from_json(blob)
to_dict¶
schedule.to_dict() -> dict
Returns the schedule model as a Python dictionary.
spec = schedule.to_dict()
validate¶
schedule.validate() -> None
Re-runs structural validation. Raises ValueError on failure.
schedule.validate()
next¶
schedule.next(after=None) -> datetime | None
Returns the first occurrence strictly after after.
from datetime import datetime, timezone
after = datetime(2026, 1, 13, tzinfo=timezone.utc)
schedule.next(after)
previous¶
schedule.previous(before=None) -> datetime | None
Returns the last occurrence strictly before before.
before = datetime(2026, 1, 13, tzinfo=timezone.utc)
schedule.previous(before)
until¶
schedule.until(before, after=None) -> list[datetime]
Returns occurrences in (after, before), ascending.
end = datetime(2026, 2, 1, tzinfo=timezone.utc)
schedule.until(end, after)
since¶
schedule.since(after, before=None) -> list[datetime]
Returns occurrences in (after, before), descending.
start = datetime(2026, 1, 1, tzinfo=timezone.utc)
schedule.since(start)
upcoming¶
schedule.upcoming(n, after=None) -> list[datetime]
Returns the next n occurrences strictly after after, ascending.
schedule.upcoming(5, after)
Trace Methods¶
Trace methods return dictionaries with instant and reason.
Method |
Return type |
Order |
|---|---|---|
|
|
— |
|
|
— |
|
|
ascending |
|
|
descending |
|
|
ascending |
Reason strings include:
Reason form |
Meaning |
|---|---|
|
Base occurrence was kept. |
|
Occurrence was moved from the local date. |
|
Base occurrence was shifted through DST gap. |
|
Made-up occurrence was shifted through DST gap. |
trace = schedule.next_trace(after)
# {"instant": datetime(..., tzinfo=timezone.utc), "reason": "base"}
is_occurrence¶
schedule.is_occurrence(instant) -> bool
Returns whether instant is an occurrence of the schedule.
schedule.is_occurrence(datetime(2026, 1, 20, 22, 30, tzinfo=timezone.utc))
count_between¶
schedule.count_between(after, before) -> int
Returns the number of occurrences strictly in (after, before).
schedule.count_between(after, end)
describe¶
schedule.describe() -> str
Returns a human-readable summary of the base recurrence, timezone, overlay count, and makeup presence.
schedule.describe()
# "Every Monday at 17:30 America/New_York, with 1 overlay(s), with makeup"
Iteration¶
iter(schedule) -> iterator[datetime]
schedule.iter_between(after, before) -> iterator[datetime]
schedule.iter_upcoming(n, after=None) -> iterator[datetime]
instant in schedule -> bool
iter(schedule) requires the schedule to have an end bound. It starts from
start, or from the current UTC time when start is absent.
for instant in bounded_schedule:
print(instant)
list(schedule.iter_between(after, end))
list(schedule.iter_upcoming(3, after))
instant in schedule
Typed Model¶
dateme.model mirrors the Schedule model as dataclasses
and enums. Builders expose to_dict() and schedules expose to_json().
from dateme import (
Schedule,
MonthlyByWeekday,
NthWeekday,
Nth,
Weekday,
MonthDay,
Overlay,
CalendarId,
OverlayRule,
Makeup,
)
from dateme import model as m
spec = m.Schedule(
freq=MonthlyByWeekday([NthWeekday(Nth.THIRD, Weekday.FRI)], "16:00"),
timezone="America/New_York",
overlays=[Overlay(CalendarId.NYSE_TRADING_DAY, OverlayRule.ONLY)],
makeup=Makeup.NONE,
)
schedule = Schedule(spec)
Builder families:
Family |
Builders |
|---|---|
Frequencies |
|
Calendar specs |
|
Overlays |
|
Makeup |
|
Date helpers |
|
- class dateme.Schedule(spec, calendar_provider=None)¶
Bases:
objectA recurrence schedule built from its JSON representation.
A schedule is a frequency in an IANA timezone, plus optional calendar overlays, a makeup strategy, and start/end bounds. Its methods compute the instants the schedule fires. Reference instants are timezone-aware
datetimeobjects; when omitted they default to the current time (UTC).- __contains__(key, /)¶
Return key in self.
- __iter__()¶
Implement iter(self).
- count_between(after, before)¶
Count occurrences strictly in (after, before).
- describe()¶
Human-readable summary.
- static from_dict(spec, calendar_provider=None)¶
Build a schedule from a
dictor typeddateme.modelbuilder.
- static from_json(json, calendar_provider=None)¶
Build a schedule from its JSON representation.
- is_occurrence(instant)¶
Whether instant is an occurrence of this schedule.
- iter_between(after, before)¶
Iterate occurrences in (after, before), ascending.
- iter_upcoming(n, after=None)¶
Iterate the next n occurrences strictly after after (default: now).
- next(after=None)¶
First occurrence strictly after after (default: now).
- next_trace(after=None)¶
First occurrence trace strictly after after (default: now).
- previous(before=None)¶
Last occurrence strictly before before (default: now).
- previous_trace(before=None)¶
Last occurrence trace strictly before before (default: now).
- since(after, before=None)¶
Occurrences in (after, before), descending. since(start)[0] == previous().
- since_trace(after, before=None)¶
Occurrence traces in (after, before), descending.
- to_dict()¶
Serialize back to a
dict.
- to_json()¶
Serialize back to a JSON string.
- until(before, after=None)¶
Occurrences in (after, before), ascending. until(end)[0] == next().
- until_trace(before, after=None)¶
Occurrence traces in (after, before), ascending.
- upcoming(n, after=None)¶
The next n occurrences strictly after after (default: now), ascending.
- upcoming_trace(n, after=None)¶
The next n occurrence traces strictly after after (default: now), ascending.
- validate()¶
Structural validation. Raises ValueError on an invalid schedule.
Typed builders for the dateme schedule model.
These dataclasses and enums mirror the JSON schedule model. Build a structure
from them and pass it to dateme.Schedule (or call to_dict() /
to_json()). Construction performs light validation; the authoritative
structural check remains dateme.Schedule.validate().
- class dateme.model.MakeupStep(direction: Makeup, max_hops: int | None = None)[source]¶
Bases:
objectOne cascade makeup step.
- class dateme.model.WeekdayMakeup(mon: Makeup | None = None, tue: Makeup | None = None, wed: Makeup | None = None, thu: Makeup | None = None, fri: Makeup | None = None, sat: Makeup | None = None, sun: Makeup | None = None, default: Makeup | None = None)[source]¶
Bases:
objectMakeup directions selected by the excluded date’s weekday.
- class dateme.model.CalendarDates(dates: list[str | date | datetime])[source]¶
Bases:
objectAn inline set of local dates.
- class dateme.model.CalendarUnion(union: list[CalendarId | CalendarDates | CalendarUnion | CalendarDiff | CustomCalendar])[source]¶
Bases:
objectA calendar that contains dates present in any child calendar.
- class dateme.model.CalendarDiff(diff: list[CalendarId | CalendarDates | CalendarUnion | CalendarDiff | CustomCalendar])[source]¶
Bases:
objectA calendar containing dates in the first child, minus following children.
- class dateme.model.CustomCalendar(custom: str)[source]¶
Bases:
objectA named calendar resolved by a runtime provider.
- class dateme.model.MonthDay(value: int | None = None)[source]¶
Bases:
objectA day within a month: a fixed
value(1-31), or the last day whenNone.
- class dateme.model.NthWeekday(nth: Nth, weekday: Weekday)[source]¶
Bases:
objectAn ordinal weekday within a month, e.g. the third Tuesday.
- class dateme.model.Overlay(calendar: CalendarId | CalendarDates | CalendarUnion | CalendarDiff | CustomCalendar, rule: OverlayRule, makeup: Makeup | WeekdayMakeup | list[Makeup | MakeupStep] | None = None)[source]¶
Bases:
objectA calendar filter applied to occurrences.
- class dateme.model.AnyOverlay(any: list[Overlay | AnyOverlay], makeup: Makeup | WeekdayMakeup | list[Makeup | MakeupStep] | None = None)[source]¶
Bases:
objectAn overlay group that passes when any child overlay passes.
- class dateme.model.Hourly(minute: int)[source]¶
Bases:
FrequencyEvery hour, at
minutepast the hour.
- class dateme.model.Weekly(days: list[Weekday], time: str | time)[source]¶
Bases:
FrequencyEvery selected weekday at
time.
- class dateme.model.EveryNDays(interval: int, start_date: str | date | datetime, time: str | time)[source]¶
Bases:
FrequencyEvery
intervaldays fromstart_dateattime.
- class dateme.model.EveryNWeeks(interval: int, start_date: str | date | datetime, days: list[Weekday], time: str | time)[source]¶
Bases:
FrequencyEvery
intervalweeks fromstart_dateon selected weekdays.
- class dateme.model.MonthlyByDay(days: list[MonthDay], time: str | time)[source]¶
Bases:
FrequencySelected days-of-month at
time.
- class dateme.model.MonthlyByWeekday(weekdays: list[NthWeekday], time: str | time)[source]¶
Bases:
FrequencySelected nth-weekdays at
time.
- class dateme.model.Yearly(month: int, day: MonthDay, time: str | time)[source]¶
Bases:
FrequencyOnce a year in
monthondayattime.
- class dateme.model.Quarterly(month: int, day: MonthDay, time: str | time)[source]¶
Bases:
FrequencyEvery quarter on
monthwithin quarter (1-3), ondayattime.
- class dateme.model.CustomCron(expr: str)[source]¶
Bases:
FrequencyFive-field cron expression in schedule-local time.
- class dateme.model.Schedule(freq: ~dateme.model.Frequency, timezone: str, overlays: list[~dateme.model.Overlay | ~dateme.model.AnyOverlay] = <factory>, makeup: ~dateme.model.Makeup | ~dateme.model.WeekdayMakeup | list[~dateme.model.Makeup | ~dateme.model.MakeupStep] = Makeup.NONE, max_makeup_hops: int | None = None, makeup_failure: ~dateme.model.MakeupFailure = MakeupFailure.SKIP, makeup_only_on: list[~dateme.model.Weekday] | None = None, makeup_within_week: bool = False, makeup_exclude_weekends: bool = False, makeup_before_next: bool = False, skip_if_consecutive_excluded: int | None = None, max_skip_gap: int | None = None, start: str | ~datetime.datetime | None = None, end: str | ~datetime.datetime | None = None)[source]¶
Bases:
objectA complete schedule spec.
Pass an instance to
dateme.Scheduleto compute occurrences, or callto_dict()/to_json()for the storable form.