# DateTimePlugin ## Purpose Injects current date and time values into templates using a flexible, token-based formatting syntax. Because date-time generation depends on the system clock, the plugin accepts an injectable `Clock` from `@suaveplan/types` so tests can produce deterministic output without real-time coupling. All four token types — date, time, datetime, and Unix timestamp — are handled by a single plugin instance to minimise regex passes per render. ## Features - `{_date}` — current date formatted as `YYYY-MM-DD`. - `{_date:YYYY/MM/DD}` — custom date format using any combination of supported tokens. - `{_time}` — current time formatted as `HH:mm:ss`. - `{_time:HH:mm}` — custom time format. - `{_datetime}` — full datetime `YYYY-MM-DD HH:mm:ss`. - `{_datetime:YYYY/MM/DD HH:mm}` — custom datetime format. - `{_timestamp}` — Unix milliseconds as a decimal string. - `{_timestamp:s}` — Unix seconds (floored). - Format tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`, `ss`, `SSS`. - Injectable `Clock` for deterministic testing. ## Usage: Basic Example ```ts import { TemplateEngine, createDateTimePlugin } from "@suaveplan/templates"; const engine = new TemplateEngine().use(createDateTimePlugin()); // Actual output depends on system time; shown illustratively engine.parse("Today is {_date}", {}); // "Today is 2024-06-15" engine.parse("Time: {_time}", {}); // "Time: 14:30:00" engine.parse("Epoch: {_timestamp}", {}); // "Epoch: 1718451000000" ``` ## Usage: Advanced Example ```ts import { TemplateEngine, createDateTimePlugin } from "@suaveplan/templates"; import type { Clock } from "@suaveplan/types"; // Deterministic clock for tests const fixedClock: Clock = () => new Date("2024-06-15T14:30:00.500Z").getTime(); const engine = new TemplateEngine().use(createDateTimePlugin({ clock: fixedClock })); engine.parse("{_date:YYYY/MM/DD}", {}); // → "2024/06/15" engine.parse("{_datetime:DD-MM-YYYY HH:mm:ss}", {}); // → "15-06-2024 14:30:00" engine.parse("{_timestamp:s}", {}); // → "1718459400" ``` ## API Reference ### `DateTimePluginOptions` | Property | Type | Description | |----------|------|-------------| | `clock` | `Clock` (optional) | Injectable clock; defaults to `() => Date.now()` | ### `createDateTimePlugin(opts?): Plugin` Returns a `Plugin` with: - `name: "datetime"` - `priority: PluginPriority.HIGH` (80) - `pattern: /\{_(date|time|datetime|timestamp)(?::([^}]+))?\}/g` The pattern captures two groups: 1. Type keyword: `date`, `time`, `datetime`, or `timestamp` 2. Optional format string or modifier (`s` for Unix seconds) **transform(match)**: Calls `clock()` to obtain the current epoch milliseconds, wraps it in a `Date`, and dispatches on the type keyword. Delegates formatting to `formatDate(date, pattern)`. Returns the original match string for unrecognised type keywords (defensive — cannot occur given the pattern). ## Implementation Notes - The `Clock` type from `@suaveplan/types` is defined as `() => number`, returning epoch milliseconds. The plugin wraps this with `new Date(clock())` to feed `formatDate`. - `formatDate` performs simple token-by-token string replacement in a defined order (longest tokens first) so there is no ambiguity between `MM` and `m` characters in the pattern. - `{_timestamp:s}` uses `Math.floor(now.getTime() / 1000)` to truncate to seconds without rounding, matching the behaviour of POSIX `time()`. - Runs at `HIGH` priority so date/time tokens are resolved before MEDIUM-priority transforms (which might want to further format the resulting string via `CaseTransformPlugin`).