Metadata-Version: 2.4
Name: larzcron
Version: 0.1.0
Summary: Cron expression parsing and an in-process scheduler in pure Python. Ranges, steps, names, macros, next/previous, cron + interval jobs. Zero dependencies.
Author: larz-scripter
License: MIT
Project-URL: Homepage, https://github.com/larz-scripter/larzcron
Project-URL: Repository, https://github.com/larz-scripter/larzcron
Project-URL: Documentation, https://github.com/larz-scripter/larzcron#readme
Project-URL: Issues, https://github.com/larz-scripter/larzcron/issues
Keywords: cron,crontab,scheduler,scheduling,cron-expression,job-scheduler,apscheduler-alternative,zero-dependency,pure-python
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# larzcron

**Cron expressions and an in-process scheduler. Pure Python, zero dependencies.**

Parse and match standard cron expressions, compute the next/previous fire time,
and run jobs on cron schedules or fixed intervals — all in-process, with no
daemon, no service, and nothing to install.

```python
from larzcron import CronExpression
from datetime import datetime

c = CronExpression("*/15 9-17 * * mon-fri")     # every 15 min, 9-5, weekdays
c.matches(datetime(2026, 7, 27, 9, 30))         # True
c.next(datetime(2026, 7, 27, 9, 31))            # -> 2026-07-27 09:45
```

## Why

- **Zero dependencies.** No `croniter`, no `APScheduler`, no service to run — just
  the standard library.
- **Full everyday cron syntax.** `*`, ranges (`1-5`), lists (`1,3,5`), steps
  (`*/15`, `0-30/10`), three-letter names (`mon`, `jan`), Sunday as `0` *or* `7`,
  and macros (`@daily`, `@hourly`, `@weekly`, `@monthly`, `@yearly`). It even
  honours the Vixie-cron rule where a restricted day-of-month **or** day-of-week
  matches.
- **Answers the real questions.** `matches(dt)`, `next(after)`, `previous(before)`
  — parse a schedule and know exactly when it fires.
- **A scheduler when you want one.** Register cron and interval jobs and either
  run a background thread or drive it deterministically with `run_pending(now)`
  (perfect for tests and cron/lambda-style ticks).

## Install

```bash
pip install larzcron
```

## Expressions

```python
CronExpression("0 * * * *")        # top of every hour
CronExpression("*/15 * * * *")     # every 15 minutes
CronExpression("0 9-17 * * mon-fri")
CronExpression("0 0 1,15 * *")     # 1st and 15th at midnight
CronExpression("@daily")           # macros

c.matches(dt)          # bool
c.next(after)          # next datetime strictly after `after`
c.previous(before)     # previous matching datetime
```

## Scheduler

```python
from larzcron import Scheduler

sched = Scheduler()

@sched.cron("0 * * * *")     # hourly
def rollup():
    ...

@sched.every(30)             # every 30 seconds
def heartbeat():
    ...

sched.start()                # background daemon thread; sched.stop() to end
```

For tests and cron-driven environments, tick it yourself — deterministic, no
threads:

```python
sched.run_pending(now=some_datetime)   # fires whatever is due at `now`
```

Add an `on_error=lambda job, exc: ...` handler to catch job exceptions without
stopping the scheduler.

## Tests

```bash
python -m unittest discover -s tests -v      # 27 tests, zero deps
```

## The Larz stack

Pure-Python, zero-dependency building blocks: **[larz](https://github.com/larz-scripter/larz)** · **[larzchain](https://github.com/larz-scripter/larzchain)** · **[larzmoney](https://github.com/larz-scripter/larzmoney)** · **[larzcrypt](https://github.com/larz-scripter/larzcrypt)** · **[larzdb](https://github.com/larz-scripter/larzdb)** · **[larzagent](https://github.com/larz-scripter/larzagent)** · **[larzchart](https://github.com/larz-scripter/larzchart)** · **[larzmark](https://github.com/larz-scripter/larzmark)** · **[larztask](https://github.com/larz-scripter/larztask)** · **[larzvault](https://github.com/larz-scripter/larzvault)** · **[larzvm](https://github.com/larz-scripter/larzvm)** · **[larzcache](https://github.com/larz-scripter/larzcache)** · **[larzvalidate](https://github.com/larz-scripter/larzvalidate)** · **[larzid](https://github.com/larz-scripter/larzid)** · **[larzrpc](https://github.com/larz-scripter/larzrpc)** · **[larzstate](https://github.com/larz-scripter/larzstate)** · **[larzhttp](https://github.com/larz-scripter/larzhttp)** · **[larzconf](https://github.com/larz-scripter/larzconf)** · **larzcron**

## License

MIT © larz-scripter
