Format dates for any locale
Intl.DateTimeFormat turns a Date into text for any locale and time zone. The dateStyle and timeStyle shortcuts cover most needs, and formatRange renders a span of two dates without repeating the shared parts. This example formats one fixed instant in several ways.
All examples format the same instant, given in UTC.
const date = new Date("2026-06-11T12:00:00Z");dateStyle picks a complete date layout for the locale. Passing an explicit timeZone makes the output independent of the machine settings.
const fullDate = new Intl.DateTimeFormat("en-US", {
dateStyle: "full",
timeZone: "UTC",
});
console.log(fullDate.format(date)); // Thursday, June 11, 2026dateStyle and timeStyle combine into a single string.
const dateTime = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeStyle: "short",
timeZone: "UTC",
});
console.log(dateTime.format(date)); // Jun 11, 2026, 12:00 PMOther locales bring their own month names, ordering, and punctuation.
const german = new Intl.DateTimeFormat("de-DE", {
dateStyle: "full",
timeZone: "UTC",
});
console.log(german.format(date)); // Donnerstag, 11. Juni 2026
const japanese = new Intl.DateTimeFormat("ja-JP", {
dateStyle: "long",
timeZone: "UTC",
});
console.log(japanese.format(date)); // 2026年6月11日The timeZone option converts the instant before formatting. The same moment is morning in New York and evening in Tokyo.
const newYork = new Intl.DateTimeFormat("en-US", {
dateStyle: "short",
timeStyle: "long",
timeZone: "America/New_York",
});
console.log(newYork.format(date)); // 6/11/26, 8:00:00 AM EDT
const tokyo = new Intl.DateTimeFormat("en-US", {
dateStyle: "short",
timeStyle: "long",
timeZone: "Asia/Tokyo",
});
console.log(tokyo.format(date)); // 6/11/26, 9:00:00 PM GMT+9formatRange writes a date range compactly. Shared parts like the month and year appear only once.
const range = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium",
timeZone: "UTC",
});
const end = new Date("2026-06-15T12:00:00Z");
console.log(range.formatRange(date, end)); // Jun 11 – 15, 2026When the range crosses a month boundary, both months are spelled out.
const longRange = new Intl.DateTimeFormat("en-US", {
month: "long",
day: "numeric",
year: "numeric",
timeZone: "UTC",
});
const nextMonth = new Date("2026-07-02T12:00:00Z");
console.log(longRange.formatRange(date, nextMonth)); // June 11 – July 2, 2026Temporal values format through the same machinery: toLocaleString takes the same locales and options. An Instant is the Temporal analog of a Date.
const instant = Temporal.Instant.from("2026-06-11T12:00:00Z");
console.log(
instant.toLocaleString("en-US", {
dateStyle: "medium",
timeStyle: "short",
timeZone: "UTC",
}),
); // Jun 11, 2026, 12:00 PMA ZonedDateTime already carries its time zone, so no timeZone option is needed (or allowed).
const zoned = instant.toZonedDateTimeISO("Europe/Warsaw");
console.log(zoned.toLocaleString("de-DE", {
dateStyle: "full",
timeStyle: "short",
})); // Donnerstag, 11. Juni 2026 um 14:00Run this example locally using the Deno CLI:
deno run https://docs.deno.com/examples/scripts/intl_date_format.ts