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.1

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.1
File Size Uploaded
lupaxa_cronlab-0.1.1.tar.gz 9.5 kB Details

Built distribution (wheel)

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

Total release size: 22.0 kB

Release files / lupaxa_cronlab-0.1.1.tar.gz

Download URL lupaxa_cronlab-0.1.1.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
20e0eafac8ed6096bf083f6cf04706d3e1d3e5ebd18749cb5c6fd89cdca5ce5a
BLAKE2b-256 checksum
How to use checksums
1f677659d3a2bec78e1b4dacf3398a328eb1f705574e00240422643961703e3c
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 7, 2026.

Transparency log

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

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

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

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