# cron-expressions

Cron expression toolkit for standard 5-field crontab syntax (minute hour day-of-month month day-of-week): parse an expression into structured fields with expanded value sets (parse), explain any cron...


Toolkit for **standard 5-field crontab syntax** — `minute hour day-of-month month day-of-week`. Parse,
explain, build, validate, and compute the next N run times of any cron expression. Deterministic
scheduler math, pure ESM, zero dependencies.

## Tools

| Tool | Purpose |
|---|---|
| `parse` | Cron (or `@`-macro) → structured fields + expanded value sets. |
| `explain` | Cron → one plain-English sentence. Optional LLM enrichment via `options.enrich`. |
| `describe` | Fields + English + the next 3 run times in one call. |
| `build` | `{ minute, hour, dayOfMonth, month, dayOfWeek }` spec → a valid cron string. |
| `nextRuns` | The next N future run times as ISO timestamps (`count`, `from`, `tz`). |
| `validate` | Check an expression; returns `{ valid, errors, normalized }` (never throws). |
| `common` | Ready-made presets (`@daily`, every-15-minutes, weekdays-9am, business-hours, …). |

## Supported syntax

`*` any, `a-b` ranges, `a/n` and `a-b/n` steps, `a,b,c` lists, month/weekday **names**
(`JAN`, `SUN`, `MON-FRI`), Sunday as `0` or `7`, and `@`-macros: `@hourly @daily @weekly @monthly
@yearly` (`@reboot` is recognized but has no scheduled time). Follows the Vixie-cron rule: when both
day-of-month and day-of-week are restricted, a run matches if **either** matches.

## Usage

```js
import cron from './index.js';

cron.adapters.parse({ cron: '*/15 9-17 * * MON-FRI' });
await cron.adapters.explain({ cron: '0 9 * * 1-5' });        // "At 09:00, on weekdays (Monday–Friday)."
cron.adapters.build({ spec: { minute: 0, hour: 9, dayOfWeek: '1-5' } }); // "0 9 * * 1-5"
cron.adapters.nextRuns({ cron: '0 0 1 * *', count: 3 });     // next 3 first-of-month midnights (UTC)
cron.adapters.validate({ cron: '99 * * * *' });              // { valid:false, errors:[...] }
cron.adapters.common({ options: { filter: 'week' } });
```

## Hybrid intelligence

The entire scheduler (field expansion + next-run search) is deterministic and offline. `explain` and
`describe` additionally support an optional LLM path (`options.enrich: true`) that rewrites the
baseline English into a friendlier sentence, silently falling back to the built-in phrasing when no
model is reachable. Results are tagged `{ mode: 'heuristic' | 'llm' }`. No tool ever requires a model.

## DRY boundary

The existing **`cron`** pack parses human *intervals* (`"5m"` → milliseconds) and fires scheduled HTTP
actions. This pack is *crontab syntax* — a different grammar entirely. No overlap. Only cross-pack
import: `../_shared/llm.js`.


---
Source: shared/engines/adapters/domain/cron-expressions/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/cron-expressions
