The Intl API: Format Numbers, Dates, and Strings Like a Pro
Master the JavaScript Intl API for locale-aware formatting of numbers, currencies, dates, relative time, and list conjunctions.
What you'll learn
- ✓How to format numbers, currencies, and percentages with Intl.NumberFormat
- ✓How to format dates and times with Intl.DateTimeFormat
- ✓How to use RelativeTimeFormat, ListFormat, and PluralRules
Prerequisites
- •Basic JavaScript
- •Familiarity with Date objects
The Intl namespace provides locale-aware formatting for numbers, dates, strings, and more — all built into every modern JavaScript runtime. No external libraries required.
Intl.NumberFormat
Format numbers according to locale conventions, including currencies, percentages, units, and compact notation.
// Basic number formatting
const num = 1234567.89;
console.log(new Intl.NumberFormat("en-US").format(num));
// "1,234,567.89"
console.log(new Intl.NumberFormat("de-DE").format(num));
// "1.234.567,89"
console.log(new Intl.NumberFormat("en-IN").format(num));
// "12,34,567.89"
Currency formatting
function formatCurrency(amount, currency, locale = "en-US") {
return new Intl.NumberFormat(locale, {
style: "currency",
currency,
}).format(amount);
}
console.log(formatCurrency(1499.99, "USD")); // "$1,499.99"
console.log(formatCurrency(1499.99, "EUR", "de-DE")); // "1.499,99 €"
console.log(formatCurrency(1499.99, "JPY", "ja-JP")); // "¥1,500"
console.log(formatCurrency(1499.99, "GBP", "en-GB")); // "£1,499.99"
Compact notation
const compact = new Intl.NumberFormat("en-US", {
notation: "compact",
compactDisplay: "short",
});
console.log(compact.format(1200)); // "1.2K"
console.log(compact.format(1500000)); // "1.5M"
console.log(compact.format(2300000000)); // "2.3B"
Percentages and units
// Percentages
const pct = new Intl.NumberFormat("en-US", {
style: "percent",
minimumFractionDigits: 1,
});
console.log(pct.format(0.7523)); // "75.2%"
// Units
const speed = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "kilometer-per-hour",
unitDisplay: "short",
});
console.log(speed.format(120)); // "120 km/h"
const temp = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "celsius",
unitDisplay: "long",
});
console.log(temp.format(22)); // "22 degrees Celsius"
Intl.DateTimeFormat
Format dates and times according to locale conventions without reaching for date libraries.
const date = new Date("2026-07-01T14:30:00Z");
// Basic formatting
console.log(new Intl.DateTimeFormat("en-US").format(date));
// "7/1/2026"
console.log(new Intl.DateTimeFormat("en-GB").format(date));
// "01/07/2026"
console.log(new Intl.DateTimeFormat("ja-JP").format(date));
// "2026/7/1"
Detailed formatting options
const date = new Date("2026-07-01T14:30:00Z");
const detailed = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZone: "America/New_York",
timeZoneName: "short",
});
console.log(detailed.format(date));
// "Wednesday, July 1, 2026 at 10:30 AM EDT"
Format to parts
formatToParts() gives you an array of labeled tokens for custom rendering.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
const parts = formatter.formatToParts(new Date("2026-07-01"));
console.log(parts);
// [
// { type: "month", value: "July" },
// { type: "literal", value: " " },
// { type: "day", value: "1" },
// { type: "literal", value: ", " },
// { type: "year", value: "2026" }
// ]
// Build custom format
const month = parts.find((p) => p.type === "month").value;
const day = parts.find((p) => p.type === "day").value;
console.log(`${month} ${day}`); // "July 1"
Time zone conversion
function formatInTimeZone(date, timeZone, locale = "en-US") {
return new Intl.DateTimeFormat(locale, {
dateStyle: "medium",
timeStyle: "long",
timeZone,
}).format(date);
}
const now = new Date();
console.log(formatInTimeZone(now, "America/New_York"));
// "Jul 1, 2026, 10:30:00 AM EDT"
console.log(formatInTimeZone(now, "Asia/Tokyo"));
// "Jul 1, 2026, 11:30:00 PM JST"
Intl.RelativeTimeFormat
Express durations in human-readable relative terms like “3 days ago” or “in 2 hours.”
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
console.log(rtf.format(-1, "day")); // "yesterday"
console.log(rtf.format(0, "day")); // "today"
console.log(rtf.format(1, "day")); // "tomorrow"
console.log(rtf.format(-3, "hour")); // "3 hours ago"
console.log(rtf.format(2, "month")); // "in 2 months"
// Other locales
const rtfFr = new Intl.RelativeTimeFormat("fr", { numeric: "auto" });
console.log(rtfFr.format(-1, "day")); // "hier"
console.log(rtfFr.format(2, "week")); // "dans 2 semaines"
Building a smart relative time function
function timeAgo(date) {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
const now = Date.now();
const diffMs = date.getTime() - now;
const diffSec = Math.round(diffMs / 1000);
const diffMin = Math.round(diffSec / 60);
const diffHour = Math.round(diffMin / 60);
const diffDay = Math.round(diffHour / 24);
if (Math.abs(diffSec) < 60) return rtf.format(diffSec, "second");
if (Math.abs(diffMin) < 60) return rtf.format(diffMin, "minute");
if (Math.abs(diffHour) < 24) return rtf.format(diffHour, "hour");
if (Math.abs(diffDay) < 30) return rtf.format(diffDay, "day");
return rtf.format(Math.round(diffDay / 30), "month");
}
const fiveMinAgo = new Date(Date.now() - 5 * 60 * 1000);
console.log(timeAgo(fiveMinAgo)); // "5 minutes ago"
Intl.ListFormat
Join lists of items with proper locale-aware conjunctions.
const items = ["Alice", "Bob", "Charlie"];
// Conjunction (and)
const and = new Intl.ListFormat("en", { type: "conjunction" });
console.log(and.format(items)); // "Alice, Bob, and Charlie"
// Disjunction (or)
const or = new Intl.ListFormat("en", { type: "disjunction" });
console.log(or.format(items)); // "Alice, Bob, or Charlie"
// Other locales
const frList = new Intl.ListFormat("fr", { type: "conjunction" });
console.log(frList.format(items)); // "Alice, Bob et Charlie"
const deList = new Intl.ListFormat("de", { type: "conjunction" });
console.log(deList.format(items)); // "Alice, Bob und Charlie"
Intl.PluralRules
Determine the correct plural category for a number in a given locale.
const pr = new Intl.PluralRules("en");
console.log(pr.select(0)); // "other"
console.log(pr.select(1)); // "one"
console.log(pr.select(2)); // "other"
function pluralize(count, singular, plural) {
const rule = new Intl.PluralRules("en").select(count);
return `${count} ${rule === "one" ? singular : plural}`;
}
console.log(pluralize(1, "item", "items")); // "1 item"
console.log(pluralize(5, "item", "items")); // "5 items"
console.log(pluralize(0, "item", "items")); // "0 items"
For languages with more plural forms (like Arabic, which has six), PluralRules returns categories like "zero", "one", "two", "few", "many", and "other".
Intl.Collator
Locale-sensitive string comparison for sorting.
const words = ["resume", "Resume", "cafe", "cafe"];
const collator = new Intl.Collator("en", { sensitivity: "base" });
// Case-insensitive, accent-insensitive sort
console.log(words.sort(collator.compare));
Intl.Segmenter
Break text into meaningful segments: words, sentences, or grapheme clusters.
const segmenter = new Intl.Segmenter("en", { granularity: "word" });
const text = "Hello, world! How are you?";
const words = [...segmenter.segment(text)]
.filter((s) => s.isWordLike)
.map((s) => s.segment);
console.log(words);
// ["Hello", "world", "How", "are", "you"]
// Grapheme clusters handle emoji correctly
const emojiSegmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
const emoji = "family emoji test";
const graphemes = [...emojiSegmenter.segment(emoji)].map((s) => s.segment);
console.log(graphemes.length);
Combining formatters for a dashboard
function formatDashboardMetrics(locale, metrics) {
const number = new Intl.NumberFormat(locale, { notation: "compact" });
const currency = new Intl.NumberFormat(locale, {
style: "currency",
currency: metrics.currency,
notation: "compact",
});
const percent = new Intl.NumberFormat(locale, {
style: "percent",
minimumFractionDigits: 1,
});
return {
users: number.format(metrics.users),
revenue: currency.format(metrics.revenue),
growth: percent.format(metrics.growth),
};
}
console.log(
formatDashboardMetrics("en-US", {
users: 1_450_000,
revenue: 12_500_000,
growth: 0.234,
currency: "USD",
})
);
// { users: "1.5M", revenue: "$13M", growth: "23.4%" }
Performance tip: reuse formatters
Creating Intl objects has a setup cost. Reuse them when formatting multiple values.
// Bad: creates a new formatter on every call
function formatPrice(amount) {
return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(amount);
}
// Good: create once, reuse
const priceFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
function formatPriceFast(amount) {
return priceFormatter.format(amount);
}
Summary
The Intl API covers nearly every formatting need for internationalized applications:
- NumberFormat for currencies, percentages, units, and compact notation.
- DateTimeFormat for locale-aware dates, times, and time zone conversions.
- RelativeTimeFormat for human-readable relative durations.
- ListFormat for joining lists with proper conjunctions.
- PluralRules for grammatically correct pluralization.
- Collator for locale-aware string sorting.
- Segmenter for breaking text into words, sentences, or grapheme clusters.
All of these are built into the runtime with zero bundle cost. Before reaching for a formatting library, check if Intl already does what you need.
Related articles
- JavaScript JavaScript Event Loop Explained: How Async Code Really Works
Understand how the JavaScript event loop handles async operations including the call stack, microtasks, macrotasks, and execution order with practical examples.
- JavaScript JavaScript structuredClone: The Modern Deep Copy Solution
Learn how to use JavaScript structuredClone for deep copying objects, when it beats JSON.parse(JSON.stringify()), and what types it supports and cannot handle.
- JavaScript JavaScript Design Patterns Every Developer Should Know
Learn the most useful JavaScript design patterns with practical examples including Singleton, Observer, Factory, Strategy, and more for cleaner code.
- JavaScript How to Find and Fix JavaScript Memory Leaks
Learn how to detect, diagnose, and fix JavaScript memory leaks using Chrome DevTools heap snapshots, allocation timelines, and common leak patterns.