# `@suaveplan/license` — time _(no submodules)_ ## Purpose Time-encoding helpers for the four `TimeEncodingType` variants. The 72-bit payload encodes time in 18 bits with an additional 2-bit discriminator (`NONE` / `ABSOLUTE_DAYS` / `RELATIVE_DAYS` / `ABSOLUTE_TIMESTAMP`), giving four distinct expiration strategies. This module turns those numeric fields into concrete `{ isExpired, expirationDate }` records and lets callers inject a `Clock` (from `@suaveplan/types`) for deterministic test runs. ## Features - Four expiration strategies, one switch — no separate code paths per call site. - Injectable `Clock` parameter; defaults to `Date.now()` so production callers don't have to thread it through. - `getDayNumber` / `dayNumberToDate` round-trip helpers used by generation when computing absolute-day expirations. - Default-arm fall-through returns `{ isExpired: false }` for unknown encodings, matching upstream's permissive behaviour (so a future encoding variant never bricks an older validator). ## Usage: Basic ```ts import { checkExpiration } from "@suaveplan/license/time/time"; import { TimeEncodingType } from "@suaveplan/license/types/license"; const r = checkExpiration(TimeEncodingType.NONE, 0); console.log(r.isExpired); // false (perpetual) ``` ## Usage: Advanced Threading a deterministic `Clock` through to relative-day expiry: ```ts import type { Clock } from "@suaveplan/types"; import { checkExpiration } from "@suaveplan/license/time/time"; import { TimeEncodingType } from "@suaveplan/license/types/license"; const clock: Clock = () => Date.UTC(2026, 5, 17, 12, 0, 0); const creation = new Date("2026-06-01T00:00:00Z"); const r = checkExpiration( TimeEncodingType.RELATIVE_DAYS, 14, undefined, // use clock creation, clock ); ``` ## API Reference ### `getDayNumber(date?: Date, clock?: Clock): number` Days since the Unix epoch. Uses `date.getTime()` when provided, otherwise the injected `clock` (default `Date.now()`). ### `dayNumberToDate(dayNumber: number): Date` Days since Unix epoch → `Date`. ### `checkExpiration(timeEncodingType, timeValue, referenceDate?, creationDate?, clock?): { isExpired, expirationDate? }` Determine expiration for a license. `referenceDate` defaults to `new Date(clock())`. `creationDate` is consulted only for `RELATIVE_DAYS` (falls back to `referenceDate`). ## Implementation Notes The unknown-encoding default arm (`return { isExpired: false }`) is intentional — it makes adding a new encoding variant a backward- compatible change for existing validators, which is important because license keys are long-lived and may outlive the validator that originally minted them. The `clock` parameter sits last in the argument list and defaults to `Date.now()`, so the public `checkExpiration` call site stays compact in normal usage and only expands when a test needs determinism.