Formatters
Locale-aware formatters for dates and numbers in the Control Panel, built on top of the browser's Intl APIs.
Statamic ships two JavaScript formatters for rendering dates and numbers in the user's locale. They're thin wrappers around the browser's Intl.DateTimeFormat and Intl.NumberFormat APIs with a few Statamic-flavored presets and a shared locale.
import { dateFormatter, numberFormatter } from '@statamic/cms/api';
Both formatters share the same default locale. Calling setDefaultLocale() on one is reflected in the other.
Date Formatter#
The dateFormatter renders dates using the browser's Intl.DateTimeFormat with a handful of built-in presets.
Presets#
| Preset | Description |
|---|---|
datetime |
Year, month, day, hour, minute (default) |
date |
Year, month, day |
time |
Short time style |
Formatting dates#
import { dateFormatter } from '@statamic/cms/api';
dateFormatter.format('2026-03-26T20:24:21');
// en-us: 3/26/2026, 8:24 PM
// de: 26.3.2026, 20:24
dateFormatter.format('2026-03-26', 'date');
// en-us: 3/26/2026
dateFormatter.format('2026-03-26T20:24:21', 'time');
// en-us: 8:24 PM
You can pass any Intl.DateTimeFormat options object instead of a preset name:
dateFormatter.format('2026-03-26', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
// March 26, 2026
Relative dates#
Pass relative: true (or a specificity) to output a humanized relative string powered by Intl.RelativeTimeFormat.
dateFormatter.format(someDate, { relative: true }); // "3 months ago"
dateFormatter.format(someDate, { relative: 'day' }); // caps out at days
dateFormatter.format(someDate, { relative: 'hour' }); // caps out at hours
Valid specificities are minute, hour, day, week, month, and year (the default when true). When the date falls outside your specificity, it falls back to datetime — pass fallback to override:
dateFormatter.format(someDate, {
relative: 'day',
fallback: 'date',
});
Static usage#
import DateFormatter from '@statamic/cms/components/DateFormatter.js';
DateFormatter.format('2026-03-26', 'date');
Number Formatter#
The numberFormatter renders numbers and numeric ranges using Intl.NumberFormat.
Presets#
| Preset | Description |
|---|---|
decimal |
Standard decimal formatting (default) |
percent |
Multiplies by 100 and appends % |
Formatting numbers#
import { numberFormatter } from '@statamic/cms/api';
numberFormatter.format(123456789.10);
// en: 123,456,789.1
// de: 123.456.789,1
numberFormatter.format(0.25, 'percent');
// en: 25%
numberFormatter.format(1234.5, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
// en: 1,234.50
Any Intl.NumberFormat options are accepted.
Formatting ranges#
numberFormatter.formatRange(1234, 5678);
// en: 1,234–5,678
// ja-jp: 1,234~5,678
numberFormatter.formatRange(0.1, 0.2, 'percent');
// en: 10%–20%
// de: 10–20 %
Static usage#
import NumberFormatter from '@statamic/cms/components/NumberFormatter.js';
NumberFormatter.format(1234.5, 'decimal');
NumberFormatter.formatRange(1, 10);
Locale#
Both formatters default to the user's browser locale (via Intl.DateTimeFormat().resolvedOptions().locale). The default locale is shared between them, so changing it on one instance affects the other.
Reading the current locale#
dateFormatter.locale; // e.g. "en-us"
numberFormatter.locale; // same value
Setting the default locale#
import { dateFormatter, numberFormatter } from '@statamic/cms/api';
numberFormatter.setDefaultLocale('de');
dateFormatter.format('2026-03-26'); // 26.3.2026, ...
numberFormatter.format(1234.5); // 1.234,5
Or using the static accessor:
import DateFormatter from '@statamic/cms/components/DateFormatter.js';
DateFormatter.defaultLocale = 'de';
DateFormatter.defaultLocale; // "de"
Temporarily switching locales#
Use withLocale to run a callback under a different locale without leaking the change. The previous locale is always restored, even if the callback throws.
numberFormatter.withLocale('de', (formatter) => {
return formatter.format(1234.567, 'decimal'); // 1.234,567
});
// Default locale is unchanged here.