Skip to main content

CronDelta: two schedules with a differing occurrence inside a clock

CronDelta

CI PyPI Python 3.11+ License: Apache-2.0

Compare actual cron engines before changing the library behind your schedules.

Changing a cron library, its version, or its options can change when a schedule fires. CronDelta calls two installed Python engines and compares their UTC occurrences in a finite window. It reports the first proven difference, the versions and timezone data used, and whether the window was fully checked.

Quick start

Use Python 3.11+ and uv. Install the released CLI from PyPI. If the release is not yet available there, use the source installation below.

uv tool install crondelta==0.1.0
crondelta compare \
  --left-engine croniter --left-version 6.2.4 \
  --right-engine apscheduler --right-version 3.11.3 \
  --expression '0 9 1 * mon' --timezone UTC \
  --start 2026-10-01T00:00:00Z --end 2026-11-01T00:00:00Z

This returns DIFFERENT, with exit code 1. Croniter's default day-of-month/day-of-week OR rule yields October 1, 5, 12, 19, and 26 at 09:00 UTC. APScheduler's AND rule yields no occurrences in that window. The first witness is October 1 at 09:00 UTC versus a fully checked empty right-hand stream.

Changing the expression to 0 9 * * mon returns MATCH_WITHIN_WINDOW, with exit code 0. This means the streams match throughout the checked [start, end) window; it makes no claim about dates outside that window. A difference can reflect an intentional library contract.

For JSON output, add --format json. For multiple schedules, download the migration manifest and save it as migration.json in your current directory, then run:

crondelta compare --manifest migration.json --format json

The installed CLI does not include example manifests. More example manifests are in the repository. To build and install from source instead:

git clone https://github.com/0then0/crondelta.git
cd crondelta
uv build
uv tool install ./dist/crondelta-0.1.0-py3-none-any.whl
crondelta --version

Installation prepares dependencies. Running compare uses already available interpreters and libraries; it never installs packages, creates environments, executes jobs, or connects to a database.

Supported comparisons

  • Engines: croniter and APScheduler 3.x CronTrigger, using their public APIs. The locked baseline is croniter 6.2.4, APScheduler 3.11.3, and tzdata 2026.2. Historical UTC controls cover croniter 6.0.0 and APScheduler 3.11.2. Other installed versions can be requested explicitly.
  • Profiles: independent expressions, supported options, exact version requirements, and Python interpreters. This also supports comparing two versions of the same engine. Each target interpreter needs its engine and tzdata installed; it does not need a separate CronDelta installation.
  • Expressions: five fields: minute, hour, day-of-month, month, day-of-week. Six/seven fields, aliases, random/hash fields, and APScheduler 4.x are outside v0.1 scope. Each engine parses its own expression.
  • Timezones: an explicit IANA key, with both engines forced to use the tzdata wheel. Reports record its version and the timezone file's SHA-256. Comparing different timezone databases is outside v0.1 scope.
  • Evidence: exact UTC datetimes, original local time, offset, fold, and UTC round-trip. Deadlines and output/occurrence limits bound enumeration. An incomplete calculation cannot produce MATCH_WITHIN_WINDOW.

CronDelta checks trigger calculations. Scheduler execution policies such as misfires, coalescing, jitter, and catch-up are outside its scope. It does not convert expressions or repair migrations automatically.

Documentation

cron-utils provides Java parsing, validation, dialect mapping, and execution-time calculations. cronkit provides cron humanization, inventories, auditing, timelines, and crontab diffs. cron-comparison compares and benchmarks JavaScript cron implementations against fixtures. CronDelta focuses on two installed Python profiles and reproducible evidence for a specific time window.

Development

From a checkout:

uv sync --locked
uv run crondelta --version
sh scripts/verify.sh

This runs linting, tests, wheel/sdist builds, installed-package checks, and reproduction controls. See Testing and support for details.

Licensed under Apache-2.0.

Metadata

Release files for crondelta 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crondelta 0.1.0
File Size Uploaded
crondelta-0.1.0.tar.gz 60.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crondelta 0.1.0
File Interpreter ABI Platform
crondelta-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 82.3 kB

Release files / crondelta-0.1.0.tar.gz

Download URL crondelta-0.1.0.tar.gz
Size 60.2 kB
Tags Source
SHA-256 checksum
How to use checksums
34591a35f2d38b19f768bec97bcf30465f76087f8edd3e23e269094e3badca0f
BLAKE2b-256 checksum
How to use checksums
0e901e063f2dc80704dc3c7f814f5116890f630a0342bd10fdaf1977220aea94
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / crondelta-0.1.0-py3-none-any.whl

Download URL crondelta-0.1.0-py3-none-any.whl
Size 22.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e61a954cfeff18f1d1155b34323155582112c1cb0730943f44e9ee475091be57
BLAKE2b-256 checksum
How to use checksums
4f6f91386c77b275195c40f5abbdc468aafaeda4cf35dc48b7c3952d94f15f9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page