Skip to main content

Developers Toolbox

Cronlab

Validate, explain, and preview five-field Vixie cron expressions. The playground does not run jobs.

The PyPI name is lupaxa-cronlab. The import path is lupaxa.cronlab. The console script is cronlab. lupaxa is a namespace package — there is no lupaxa/__init__.py.

Install

pip install lupaxa-cronlab

Requires Python 3.10+. There are no runtime dependencies.

Note: On platforms without OS timezone data, install the tzdata package so IANA names resolve.

What it Does

cronlab speaks one dialect: Vixie crontab, the same five-field shape used by Linux crontab(5) and GitHub Actions on.schedule. Quote the expression in the shell.

cronlab validate '35 5 * * 1-5'
cronlab explain '35 5 * * 1-5'
cronlab next '35 5 * * 1-5' --timezone Europe/London --from '2026-10-04T00:00:00+01:00' --count 5
cronlab next '0 9 * * *' --from '2026-10-04T00:00:00+01:00'
cronlab --version
Flag Commands Default Meaning
--timezone next UTC IANA zone for civil cron fields
--from next now (UTC clock) Exclusive start instant
--count next 5 Number of future instants, 1–100
--json all three off Metadata envelope on stdout
--version top-level — Print cronlab and the version

Validate

cronlab validate '35 5 * * 1-5'
valid

Unsupported syntax is rejected. @daily, month names, and a sixth field are not in this dialect.

cronlab validate '@daily'
error: unsupported macro: @daily
cronlab validate '0 0 * JAN *'
error: unsupported syntax in month: JAN

Explain

cronlab explain '35 5 * * 1-5'
At 05:35 on every weekday (Monday through Friday).
cronlab explain '0 9 * * *'
At 09:00 every day.
cronlab explain '*/15 * * * *'
Every 15 minutes.
cronlab explain '0 0 1 1 *'
At 00:00 on 1 January.

Next

--from is exclusive. A run that lands exactly on the start instant is skipped. Instants always include an offset.

cronlab next '0 9 * * *' --from '2026-10-04T00:00:00+01:00' --count 3
2026-10-04T09:00:00+00:00
2026-10-05T09:00:00+00:00
2026-10-06T09:00:00+00:00
cronlab next '35 5 * * 1-5' --timezone Europe/London --from '2026-10-04T00:00:00+01:00' --count 5
2026-10-05T05:35:00+01:00
2026-10-06T05:35:00+01:00
2026-10-07T05:35:00+01:00
2026-10-08T05:35:00+01:00
2026-10-09T05:35:00+01:00

A date that can never exist is valid syntax. next searches two years from --from and then stops.

cronlab next '0 0 31 2 *' --from '2026-01-01T00:00:00Z' --count 1
error: no runs within horizon

That command exits 1.

JSON

--json writes one object. Human errors stay on stderr when the flag is off. With --json, failures still exit non-zero and put the error in the envelope.

cronlab validate '35 5 * * 1-5' --json
{"dialect": "vixie", "expression": "35 5 * * 1-5", "command": "validate", "timezone": "UTC", "from": null, "inclusive": false, "dst_policy": "skip_gap_first_fold", "horizon": {"years": 2}, "ok": true}
cronlab next '0 9 * * *' --from '2026-10-04T00:00:00+01:00' --count 3 --json
{"dialect": "vixie", "expression": "0 9 * * *", "command": "next", "timezone": "UTC", "from": "2026-10-04T00:00:00+01:00", "inclusive": false, "dst_policy": "skip_gap_first_fold", "horizon": {"years": 2}, "ok": true, "runs": ["2026-10-04T09:00:00+00:00", "2026-10-05T09:00:00+00:00", "2026-10-06T09:00:00+00:00"], "count": 3}

Dialect

Five fields, left to right: minute, hour, day-of-month, month, day-of-week. Lists, ranges, and steps (*/15, 1-10/2) are accepted. Sunday is 0 or 7.

When both day-of-month and day-of-week are not *, a time matches if either field matches. That is the Vixie rule.

Seconds, @daily macros, JAN / MON, and L / W / ? are rejected.

Time Policy

Cron fields are civil times in --timezone (default UTC). --from is an absolute instant and must include an offset or Z. A naive datetime is an error.

Nonexistent local times (spring-forward gaps) are skipped. A repeated local time (autumn fold) is returned once, at the earlier offset.

Exit Codes

Result Stdout Stderr Exit
validate success valid empty 0
explain success one or two sentences empty 0
next success one ISO instant per line empty 0
--version cronlab plus the version empty 0
Parse, validation, timezone, or --from empty, or JSON with ok:false error: … 2
No run inside the two-year horizon empty, or JSON with ok:false error: … 1

Development

make init
make python-install-dev
make python-check
The Lupaxa Project Footer

Metadata

Release files for lupaxa-cronlab 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 lupaxa-cronlab 0.1.0
File Size Uploaded
lupaxa_cronlab-0.1.0.tar.gz 9.5 kB Details

Built distribution (wheel)

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

Total release size: 22.0 kB

Release files / lupaxa_cronlab-0.1.0.tar.gz

Download URL lupaxa_cronlab-0.1.0.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6e96cac6ce94ba905d3de1ec2af84f67f5ef1018b74d45818a55aeff9cb39fcb
BLAKE2b-256 checksum
How to use checksums
dce62658754a80a921464f66ca7a232f431d76b927bc0eada006ca1cc4559807
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 4, 2026.

Transparency log

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

Download URL lupaxa_cronlab-0.1.0-py3-none-any.whl
Size 12.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
db1a7caab261fa85fc374ef24c040697bcf4712ad3067c7ce490f3a4e8f11fea
BLAKE2b-256 checksum
How to use checksums
b723b5474ec9f40470b79d83e0736734a4e517fb15e32b5832a6e1a93102f915
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 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.1

2 release files

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