Skip to content

Date & Number Format Utils

All date, time, and number formatting uses the native Intl API driven by the client-sent locale — no formatting library (ADR-008, constitution §7.16.3). The helpers live in src/lib/intl/index.ts.

The formatter helpers and the native Intl constructors they wrap:

flowchart LR
  FD["formatDate(isoDate, locale)"] --> DTF["Intl.DateTimeFormat"]
  FT["formatTime(isoInstant, locale)"] --> DTF
  FDT["formatDateTime(isoInstant, locale)"] --> DTF
  FN["formatNumber(value, locale)"] --> NF["Intl.NumberFormat"]
  FRT["formatRelativeTime(target, locale, now)"] --> RTF["Intl.RelativeTimeFormat"]
  FDD["formatDueDate(dueDate, _locale)"] --> Id["identity (YYYY-MM-DD)"]
  Locale[("client locale")] --> DTF
  Locale --> NF
  Locale --> RTF
  • formatDate(isoDate, locale) — a YYYY-MM-DD date rendered for the locale.
  • formatTime(isoInstant, locale) / formatDateTime(isoInstant, locale) — instants rendered as locale time / date-time.
  • formatNumber(value, locale) — locale-grouped numbers.
  • formatRelativeTime(target, locale, now = new Date()) — “2 days ago”-style relative phrasing (Intl.RelativeTimeFormat).
  • formatDueDate(dueDate, _locale) — due-date display (date-only).

The active locale comes from the client (message catalogs are Paraglide-compiled, ADR-008); the day boundary for date-sensitive logic is the user’s local day via localTodayISO() (see Sidebar Counts & Local-Today). Because formatting is Intl-based, it adds no bundle weight beyond the platform (§8.2).

How a value is dispatched to the right formatter by its type, with the relative-time bucket branch:

flowchart TD
  V{value kind?} -->|date-only YYYY-MM-DD| FD["formatDate (UTC, dateStyle medium)"]
  V -->|instant, time| FT["formatTime (timeStyle short)"]
  V -->|instant, date + time| FDT["formatDateTime"]
  V -->|number| FN["formatNumber (locale-grouped)"]
  V -->|due date| FDD["formatDueDate (identity)"]
  V -->|relative| FRT{abs diff?}
  FRT -->|< 60s| Sec["second"]
  FRT -->|< 60m| Mn["minute"]
  FRT -->|< 24h| Hr["hour"]
  FRT -->|else| Dy["day"]

Related: Sidebar Counts & Local-Today, Task Attributes API (due dates), My Day & Owner-Scoped Views.