The Intl API is one of JavaScript's most powerful and least-known features. Master Intl.DateTimeFormat, Intl.RelativeTimeFormat, and timezone handling for global apps.
Formatting dates, numbers, and currencies correctly for different locales is surprisingly complex. The Vietnamese date format is ngày 3 tháng 3, 2025 — not 03/03/2025. German uses commas for decimals: 1.234,56. Arabic numbers flow right-to-left. Before Intl, developers shipped multi-megabyte i18n libraries to handle this. The Intl API does it natively, in ~5KB.
// Basic formatting
new Intl.DateTimeFormat("en-US").format(new Date())
// "3/3/2025"
new Intl.DateTimeFormat("de-DE").format(new Date())
// "3.3.2025"
new Intl.DateTimeFormat("vi-VN").format(new Date())
// "3/3/2025" (uses / separator, but with Vietnamese locale context)
// Full date with time
new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeStyle: "long",
timeZone: "America/New_York"
}).format(new Date())
// "Monday, March 3, 2025 at 10:30:00 AM EST"
// Individual components
new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
}).format(new Date())
// "Monday, March 3, 2025"
JavaScript uses IANA timezone identifiers (e.g., America/New_York, Asia/Ho_Chi_Minh). These are more precise than abbreviations like "EST" (which is ambiguous — Brazil also has "EST").
// Get user's local timezone
Intl.DateTimeFormat().resolvedOptions().timeZone
// "Asia/Ho_Chi_Minh" (Vietnam)
// "America/Los_Angeles" (US Pacific)
// Display the same moment in multiple timezones
const now = new Date()
const timezones = ["UTC", "America/New_York", "Europe/London", "Asia/Tokyo", "Asia/Ho_Chi_Minh"]
timezones.forEach(tz => {
const formatted = new Intl.DateTimeFormat("en-US", {
timeZone: tz,
hour: "2-digit",
minute: "2-digit",
timeZoneName: "short"
}).format(now)
console.log(`${tz.padEnd(25)} ${formatted}`)
})
// Get hours/minutes in a specific timezone
function getTimeInZone(date, timezone) {
const parts = new Intl.DateTimeFormat("en-US", {
timeZone: timezone,
hour: "numeric",
minute: "numeric",
hour12: false
}).formatToParts(date)
const hour = parts.find(p => p.type === "hour")?.value
const minute = parts.find(p => p.type === "minute")?.value
return `${hour}:${minute}`
}
getTimeInZone(new Date(), "Asia/Ho_Chi_Minh") // "17:30" (UTC+7)
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" })
rtf.format(-1, "day") // "yesterday"
rtf.format(1, "day") // "tomorrow"
rtf.format(-3, "hour") // "3 hours ago"
rtf.format(2, "week") // "in 2 weeks"
// Vietnamese
const rtfVI = new Intl.RelativeTimeFormat("vi", { numeric: "auto" })
rtfVI.format(-1, "day") // "hôm qua"
rtfVI.format(1, "week") // "tuần sau"
// Smart relative time utility
function timeAgo(date) {
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" })
const seconds = Math.floor((Date.now() - date.getTime()) / 1000)
const ranges = [
[60, "second", 1],
[3600, "minute", 60],
[86400, "hour", 3600],
[604800, "day", 86400],
[2592000, "week", 604800],
[31536000, "month", 2592000],
[Infinity, "year", 31536000]
]
for (const [limit, unit, divisor] of ranges) {
if (Math.abs(seconds) < limit) {
return rtf.format(-Math.round(seconds / divisor), unit)
}
}
}
timeAgo(new Date(Date.now() - 90000)) // "2 minutes ago"
timeAgo(new Date(Date.now() - 86400000 * 3)) // "3 days ago"
// Currency
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(1234.5)
// "$1,234.50"
new Intl.NumberFormat("vi-VN", { style: "currency", currency: "VND" }).format(25000000)
// "25.000.000 ₫"
// Compact notation
new Intl.NumberFormat("en", { notation: "compact" }).format(1500000)
// "1.5M"
// Percentages
new Intl.NumberFormat("en", { style: "percent", minimumFractionDigits: 1 }).format(0.8534)
// "85.3%"
const lf = new Intl.ListFormat("en", { style: "long", type: "conjunction" })
lf.format(["apples", "bananas", "oranges"])
// "apples, bananas, and oranges"
const lfVI = new Intl.ListFormat("vi")
lfVI.format(["Hà Nội", "TP. Hồ Chí Minh", "Đà Nẵng"])
// "Hà Nội, TP. Hồ Chí Minh và Đà Nẵng"
HeoLab's World Clock is built entirely on Intl.DateTimeFormat — displaying the current time across 40+ cities with no external libraries.
The Intl API eliminates the need for heavy date/i18n libraries in most cases. DateTimeFormat handles timezone conversion and locale-appropriate formatting; RelativeTimeFormat gives you "2 hours ago" strings in any language; NumberFormat formats currencies and percentages correctly. Reach for Intl first before adding moment.js or similar dependencies.
World Clock
See the current time in multiple cities simultaneously. Live updates every second with day/night indicators.
Unix Timestamp Converter
Convert Unix timestamps to human-readable dates and vice versa. Supports all major timezone formats.
Date Calculator
Add or subtract days, weeks, months, or years from any date. See the result in multiple formats.