{
  "schema": "leumas.docs.page/1",
  "id": "adapter:domain/datetime",
  "slug": "adapters/domain/datetime",
  "kind": "capabilities",
  "bucket": "package",
  "title": "datetime (adapter system)",
  "name": "datetime",
  "eyebrow": "adapter system",
  "chip": null,
  "summary": "Date/time math capability pack using JS Date + Intl only (zero dependencies): duration breakdown between two dates, add a duration, business-day counting/adding (Mon-Fri minus holidays), ISO week...",
  "keywords": [
    "datetime",
    "mon-fri",
    "holidays",
    "iana",
    "isweekend",
    "isleapyear",
    "daysinmonth",
    "intl"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# datetime (adapter system)\n\nDate/time **math** pack built purely on the JS `Date` + `Intl` built-ins (both always present in Node)\n— **zero dependencies**. Every tool takes ONE args object. Dates are accepted loosely (ISO string,\nepoch-ms number, or anything `Date.parse` handles); calendar arithmetic runs in UTC so it's\ndeterministic and DST-agnostic.\n\n## Tools (`adapters`)\n\n| tool | args | result |\n|------|------|--------|\n| `durationBetween` | `{ from, to, unit? }` | `{ breakdown:{years,months,days,hours,minutes,seconds}, totals, negative }` |\n| `addDuration` | `{ date, years?,months?,days?,hours?,minutes?,seconds? }` | `{ iso, epoch }` |\n| `businessDays` | `{ from, to, holidays? }` | `{ businessDays, holidaysExcluded }` — Mon-Fri, inclusive of both ends |\n| `addBusinessDays` | `{ date, days, holidays? }` | `{ iso, epoch, date }` |\n| `weekNumber` | `{ date }` | `{ week, isoYear, label }` — ISO-8601 week |\n| `dayOfYear` | `{ date }` | `{ dayOfYear, daysInYear }` |\n| `timeAgo` | `{ date, now? }` | `{ phrase, unit, value, future }` — e.g. \"3 days ago\" / \"in 2 hours\" |\n| `toTimezone` | `{ date, timeZone }` | `{ wallClock, parts, formatted }` via Intl in that IANA zone |\n| `format` | `{ date, locale?, options? }` | `{ formatted }` via `Intl.DateTimeFormat` |\n| `isWeekend` | `{ date }` | `{ isWeekend, weekday }` |\n| `isLeapYear` | `{ year }` | `{ isLeapYear }` |\n| `daysInMonth` | `{ year, month }` | `{ days }` (month is 1-12) |\n| `parse` | `{ input }` | `{ iso, epoch, valid, year, month, day, weekday }` — tolerant |\n\n## Usage\n\n```js\nimport datetime from './index.js';\ndatetime.adapters.businessDays({ from: '2024-01-01', to: '2024-01-05' }); // → { businessDays: 5, ... }\ndatetime.adapters.timeAgo({ date: '2024-01-01', now: '2024-01-04' });     // → { phrase: '3 days ago', ... }\ndatetime.adapters.weekNumber({ date: '2024-01-01' });                     // → { week: 1, isoYear: 2024, ... }\ndatetime.adapters.toTimezone({ date: '2024-06-01T12:00:00Z', timeZone: 'America/New_York' });\n```\n\n## DRY boundary notes\n\n- **Does NOT** parse interval strings like `\"5m\"` / `\"2h\"` into milliseconds — that belongs to the\n  **`cron`** pack.\n- **Does NOT** do generic ISO coercion of arbitrary/loose types — that's **a-transformation\n  `timestamps.*`**. (This pack coerces inputs only as a convenience for its own math.)\n- **Does NOT** render calendars (month grids, week layouts) — that's the **`calendar`** pack.\n- `toTimezone` returns the wall-clock **parts** in the requested zone via `Intl` (which carries the\n  real IANA tz db in Node). True raw numeric tz-offset arithmetic without a bundled tz db is out of\n  scope here.\n\nThis pack = **duration / business-day / timezone / relative-time math.**\n",
  "source": {
    "path": "shared/engines/adapters/domain/datetime/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 2922,
    "hash": "87ade77ecbddf9be9fbefd033e4594d4c1672e5e"
  },
  "urls": {
    "html": "/p/adapters/domain/datetime",
    "json": "/docs/adapters/domain/datetime.json",
    "md": "/docs/adapters/domain/datetime.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
