first commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# recurrence-generate
|
||||
|
||||
## Purpose
|
||||
|
||||
`recurrence-generate` provides the internal generator functions that produce infinite sequences of candidate dates for each recurrence frequency supported by `@suaveplan/datetime`. Each generator yields dates strictly after a given `from` anchor, and the `generateCandidates` dispatcher routes to the correct generator based on `RecurrenceRule.freq`.
|
||||
|
||||
This module is an internal implementation detail. Public callers should use `expandRecurrence` and `nextOccurrence` from `recurrence.ts`.
|
||||
|
||||
## Features
|
||||
|
||||
- `generateDaily` — daily step with optional `BYDAY` weekday filter
|
||||
- `generateWeekly` — weekly step, either plain (same weekday) or with `BYDAY` multi-day selection
|
||||
- `generateMonthly` — monthly step supporting `BYMONTHDAY`, `BYDAY`, or plain monthly recurrence
|
||||
- `generateYearly` — yearly step supporting `BYMONTHDAY`, `BYDAY`, or plain yearly recurrence
|
||||
- `generateCandidates` — dispatcher that routes to the correct generator from `RecurrenceRule.freq`
|
||||
- All generators are infinite; termination is enforced by callers (`count` / `until` / `AbortSignal`)
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { generateCandidates } from "./recurrence-generate.js";
|
||||
|
||||
const rule = { freq: "daily" as const, count: 5 };
|
||||
const from = new Date(2024, 0, 1);
|
||||
|
||||
const gen = generateCandidates(rule, from);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
console.log(gen.next().value?.toDateString());
|
||||
}
|
||||
// Tue Jan 02 2024 … Sat Jan 06 2024
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { generateCandidates } from "./recurrence-generate.js";
|
||||
|
||||
// Monthly with BYMONTHDAY — yields the 15th of each month
|
||||
const rule = {
|
||||
freq: "monthly" as const,
|
||||
byMonthDay: [15],
|
||||
};
|
||||
const from = new Date(2024, 0, 1);
|
||||
const gen = generateCandidates(rule, from);
|
||||
|
||||
const first = gen.next().value!;
|
||||
console.log(first.toDateString()); // Mon Jan 15 2024
|
||||
|
||||
const second = gen.next().value!;
|
||||
console.log(second.toDateString()); // Thu Feb 15 2024
|
||||
|
||||
// Weekly with BYDAY — yields Mon/Wed/Fri
|
||||
const weeklyRule = {
|
||||
freq: "weekly" as const,
|
||||
byDay: [1, 3, 5] as const,
|
||||
};
|
||||
const weeklyGen = generateCandidates(weeklyRule, new Date(2024, 2, 11));
|
||||
console.log(weeklyGen.next().value?.getDay()); // 3 (Wed Mar 13)
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `generateCandidates(rule: RecurrenceRule, from: Date): Generator<Date>`
|
||||
|
||||
Unified dispatcher. Routes to the frequency-specific generator based on `rule.freq`. All yielded dates are strictly after `from`.
|
||||
|
||||
### `generateDaily(rule, from, interval): Generator<Date>`
|
||||
|
||||
Steps `interval` days at a time. If `rule.byDay` is set, only yields dates whose `getDay()` is in the list.
|
||||
|
||||
### `generateWeekly(rule, from, interval): Generator<Date>`
|
||||
|
||||
If `rule.byDay` is set: anchors to the Sunday of the current week, then emits the specified weekdays in sorted order each `interval * 7` days. Without `byDay`: yields the same weekday every `interval * 7` days.
|
||||
|
||||
### `generateMonthly(rule, from, interval): Generator<Date>`
|
||||
|
||||
Three modes:
|
||||
|
||||
1. `byMonthDay` — emits the specified day-of-month values (sorted) in each month, skipping months where a day exceeds `daysInMonth`.
|
||||
2. `byDay` — scans each month and emits all days matching the weekday list.
|
||||
3. Plain — yields the same day-of-month each `interval` months using `addMonths` clamping.
|
||||
|
||||
### `generateYearly(rule, from, interval): Generator<Date>`
|
||||
|
||||
Three modes:
|
||||
|
||||
1. `byMonthDay` — emits specified day-of-month values in each year.
|
||||
2. `byDay` — advances one day at a time from the year anchor, yielding matching weekdays.
|
||||
3. Plain — yields the same date each `interval` years using `addYears`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
All generators are implemented as native ES `Generator` functions (`function*`) to enable lazy evaluation. They produce an infinite sequence; the caller (`expandRecurrence`, `nextOccurrence`) is responsible for applying `count`, `until`, and `AbortSignal` termination conditions.
|
||||
|
||||
The `generateWeekly` with `BYDAY` mode anchors to the start of the week (Sunday) on the first iteration, which means it may emit dates in the current week before advancing. Dates before or equal to `from` are filtered out with a `candidate > from` guard.
|
||||
Reference in New Issue
Block a user