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
tzdatapackage 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
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)
| File | Size | Uploaded | |
|---|---|---|---|
| lupaxa_cronlab-0.1.1.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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