croniter
Parses cron schedule strings and iterates the matching datetime values, with DST, second/year fields, and last-weekday support.
Repository Health
Technical Analysis
croniter takes a standard (or extended) cron expression and a starting datetime, then walks forward or backward to the exact moments the schedule fires. It’s the parsing and iteration engine underneath most Python scheduling code: task queues computing the next run for a periodic job, cron-expression validators in web UIs, and dashboards that need to show “next 5 runs” for a saved schedule.
Beyond the standard five-field Unix syntax, it supports optional seconds and year fields, last-day-of-month (l), nearest-weekday (W), Nth-weekday-of-month (#), hash-based expressions for spreading load across a fleet (H / @hourly-style), configurable AND/OR semantics between day-of-month and day-of-week, and DST-aware iteration when given timezone-aware datetimes.
What You Get
- A
croniterclass that wraps a cron expression and a start time, exposingget_next()/get_prev()to step through matching datetimes or Unix timestamps croniter.is_valid()andcroniter.expand()classmethods for validating and introspecting a cron string before scheduling it, including opt-instrict=Truecross-field validation (rejects impossible dates like Feb 31)- Extended syntax beyond POSIX cron: optional seconds and year fields,
l(last day of month),W/nW(nearest weekday),#(Nth weekday of month), and hash-based expressions (H,@hourlywith ahash_id) for staggering many jobs’ fire times day_orandimplement_cron_bugflags to control whether day-of-month and day-of-week combine with OR (POSIX default) or AND (fcron-style), including reproducing a known vixie-cron quirk for compatibility- Full timezone/DST awareness via
zoneinfo,pytz, ordateutil.tzwhen a timezone-awarestart_timeis supplied croniter_range()helper and the iterator protocol (all_next()/all_prev()) for pulling a bounded or unbounded sequence of fire times directly in aforloop
Common Use Cases
- Computing a job’s next scheduled run inside a task queue or scheduler (Celery beat, Airflow, custom cron-like schedulers) without shelling out to system cron
- Validating user-submitted cron expressions in a web form or admin UI before saving a scheduled job
- Generating a preview list of upcoming run times (“next 5 executions”) for a saved schedule shown in a dashboard
- Staggering many periodic jobs across a time window using hash-based (
H) expressions so they don’t all fire at the same instant - Backfilling or auditing historical run times for a cron-scheduled job by iterating backward with
get_prev()
Under The Hood
Architecture
croniter centers on a single croniter class (src/croniter/croniter.py, ~1,600 lines) that does two things: expand a cron expression string into per-field integer sets (_expand, feeding expanded, nth_weekday_of_month, and nearest_weekday state), then walk forward or backward from a timestamp field-by-field (proc_year/proc_month/proc_day_of_month/proc_day_of_week/proc_hour/proc_minute/proc_second closures inside _calc_next) until every field matches. A separate HashExpander class isolates the hash-based (H, @hourly) expansion logic from the core matching loop, keeping that fairly niche feature from complicating the primary code path. get_next/get_prev are thin wrappers over a shared _get_next, and all_next/all_prev turn that into a generator for the iterator protocol. The design is intentionally a single cohesive module rather than a layered system — appropriate for a focused parsing/iteration library where the field-matching state machine is the entire product.
Tech Stack
Pure Python (3.9+) with exactly one runtime dependency, python-dateutil, used for relativedelta (DST-safe date arithmetic) and tzutc/datetime_exists (DST-transition detection). No C extensions. Packaged with hatchling and uv-managed dependency groups (dev, lint, mypy, format, tox, release); tox.ini wires pytest+coverage for tests, ruff for lint and formatting, and mypy for type-checking into a single tox -e lint,mypy,fmt gate.
Code Quality
161 test functions spread across purpose-specific files (test_croniter.py, test_croniter_range.py, test_croniter_dst_repetition.py, test_croniter_hash.py, test_croniter_random.py, plus a test_croniter_speed.py performance check), run via pytest with branch coverage. A dedicated custom exception hierarchy (CroniterError, CroniterBadCronError, CroniterBadDateError, CroniterBadTypeRangeError, CroniterNotAlphaError, CroniterUnsupportedSyntaxError) replaces generic ValueErrors with specific, catchable failure modes. CI (cicd.yml) runs the lint/mypy/format gate plus the full test suite across Python 3.9 through 3.13, and a separate zizmor.yml workflow scans the GitHub Actions workflows themselves for supply-chain issues — a level of CI hygiene beyond most libraries this size.
API Design
The public surface is deliberately small: construct a croniter(expr, start_time), then call get_next()/get_prev() repeatedly, or use it directly as an iterator. Sensible defaults (POSIX OR semantics, ret_type=float) mean the common case needs no keyword arguments, while power users get explicit opt-in flags (day_or, hash_id, implement_cron_bug, expand_from_start_time, second_at_beginning) for the less common behaviors. The README documents every extended feature with runnable, copy-pasteable examples rather than prose-only explanation, which keeps the learning curve low despite the fairly deep feature set (leap years, DST, hash expressions, AND/OR day semantics) hiding underneath.
Used by 15 apps in this directory
Foxel
File Storage
Self-hosted private cloud storage with AI semantic search and a pluggable multi-backend file management system.
OpenViking
AI Development · AI Memory · Databases
An open-source context database that gives AI agents a unified filesystem for memory, resources, and skills with hierarchical tiered retrieval.
PostHog
Ab Testing Experimentation · Analytics · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Skyvern
AI Agents · Automation
Skyvern (YC S2023) automates browser-based workflows by pairing LLMs with computer vision, letting agents click, fill, and extract data on sites they've never seen, without brittle XPath selectors that break on every layout change.
SurfSense
AI Assistants · Search
The open-source, unlimited NotebookLM alternative with real-time collaboration, a desktop app, and no vendor lock-in.
Tracecat
AI Agents · Automation · Security
Open-source agentic security automation platform that runs AI agents and durable workflows at scale with sandboxed execution.