active-format
Formatting and parsing of dates, numbers, currency amounts, percentages and byte counts, for people and for machines.
@workspace/active-format 1.0.0Developmentunreleased, in development in Foundationbaseline ce081dc3
@workspace/active-format turns values into text a reader understands, and reads typed text back
into values. Every human-readable call receives its presentation explicitly: the reader's
language, optionally a notation profile and a time zone. Nothing is read from a provider, a cookie,
a header, the environment or a host default.
A first callClient
| Language | Calendar day | Amount |
|---|---|---|
| en | 31 Dec 2026 | €1,234.50 |
| nl | 31 dec. 2026 | € 1.234,50 |
| de | 31. Dez. 2026 | 1.234,50 € |
// apps/docs/examples/format/first-format.tsx'use client';
import {formatCurrency, formatDateOnly} from '@workspace/active-format';import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow,} from '@workspace/active-ui/components/primitives/table';
const LANGUAGES = ['en', 'nl', 'de'] as const;
/** The first call: the same values, the presentation passed explicitly. */export default function FirstFormat() { return ( <Table> <TableHeader> <TableRow> <TableHead>Language</TableHead> <TableHead>Calendar day</TableHead> <TableHead>Amount</TableHead> </TableRow> </TableHeader> <TableBody> {LANGUAGES.map((language) => ( <TableRow key={language}> <TableCell className="font-mono">{language}</TableCell> <TableCell suppressHydrationWarning> {formatDateOnly('2026-12-31', language)} </TableCell> <TableCell suppressHydrationWarning> {formatCurrency({amount: 1234.5, currency: 'EUR'}, language)} </TableCell> </TableRow> ))} </TableBody> </Table> );}When you use it#
- You show dates, times, numbers, amounts, percentages, sizes or durations to a person.
- You read a date, a time or a number that a person typed.
- You need a machine form that never depends on language or zone (
yyyy-MM-dd, ISO instants, plain dot decimals). - You build a component or a package that formats values but must not decide the reader's language itself: it takes the presentation from its caller and passes it on.
What it does not do#
- No words. It does not translate. A component that shows text receives that text from its caller.
- No language choice. Your application decides the reader's language and passes it in. Which languages a product offers is your policy.
- No hidden clock. Only
todayIsoDate(timeZone)andresolveRecencywithout itsnowoption read the current time; every other function takes its moment from you. - No framework. It has no React, no provider and no side effects. It runs in Node.js and in the browser alike.
How it fits together#
| You have | You use |
|---|---|
| only a language | a BCP 47 tag such as 'en' or 'nl' as the presentation |
| a language plus user preferences | compose once, and pass the result everywhere |
| a calendar day (a birthday, a due date) | format: it never shifts with a zone |
| a moment in time | format or format, in the presentation's time zone |
| an amount of money | format: the currency comes from the data |
| text a person typed | classify, classify, classify |
| a value for a file, an API or a URL | format, format, format |
Dependencies#
date-fns and @date-fns/tz. No other workspace package, no peer dependency. Two functions need
more than an ES2022 Intl; see Errors and runtime.
Next#
- Getting started: receive the package and make the first call.
- Presentation: the one input every formatter takes.