Format Dates with JavaScript Intl DateTimeFormat
The Intl.DateTimeFormat object is a built-in JavaScript
API that provides language-sensitive date and time formatting without
the need for external libraries. This article explains how
Intl.DateTimeFormat works, how it resolves locale
conventions, and how you can configure options to control components,
time zones, and calendars.
Basic Syntax and Mechanism
The Intl.DateTimeFormat constructor takes two optional
arguments: a locale identifier (or array of identifiers) and an options
object. It compiles an internal formatter tailored to the specified
locale’s conventions.
const date = new Date('2025-05-15T14:30:00Z');
// Format using US English conventions (MM/DD/YYYY)
const usFormatter = new Intl.DateTimeFormat('en-US');
console.log(usFormatter.format(date)); // "5/15/2025"
// Format using German conventions (DD.MM.YYYY)
const deFormatter = new Intl.DateTimeFormat('de-DE');
console.log(deFormatter.format(date)); // "15.5.2025"When you omit the locale parameter or pass undefined,
JavaScript uses the runtime’s default locale (usually the browser or
operating system setting).
Specifying Locales
Locales are defined using standard BCP 47 language tags (such as
en-US, fr-CA, ja-JP, or
ar-EG). You can also pass an array of locales to establish
a fallback hierarchy:
// Tries Breton first; if unsupported, falls back to French, then default
const formatter = new Intl.DateTimeFormat(['br', 'fr']);Locales can include Unicode extension keys to specify preferences like calendar types or numbering systems:
// Format using the Japanese imperial calendar
const jpCalendar = new Intl.DateTimeFormat('ja-JP-u-ca-japanese');
console.log(jpCalendar.format(date)); // "R7/5/15" (Reiwa 7)Using dateStyle and
timeStyle
The modern Intl.DateTimeFormat API provides high-level
convenience properties: dateStyle and
timeStyle. They accept "full",
"long", "medium", or "short".
const fullFormat = new Intl.DateTimeFormat('en-GB', {
dateStyle: 'full',
timeStyle: 'short'
});
console.log(fullFormat.format(date));
// "Thursday, 15 May 2025 at 15:30"Granular Formatting Options
When predefined styles do not fit your requirements, you can customize individual date and time tokens:
weekday:"long","short","narrow"year:"numeric","2-digit"month:"numeric","2-digit","long","short","narrow"day:"numeric","2-digit"hour,minute,second:"numeric","2-digit"hour12:trueorfalse(overrides the locale’s default 12/24-hour preference)timeZoneName:"long","short","shortOffset","longOffset","shortGeneric","longGeneric"
const customFormatter = new Intl.DateTimeFormat('es-ES', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: false
});
console.log(customFormatter.format(date));
// "jueves, 15 de mayo de 2025, 16:30"Time Zone Handling
By default, dates are formatted in the user’s local time zone. You
can explicitly set a target time zone using IANA time zone identifiers
(such as "UTC", "America/New_York", or
"Asia/Tokyo").
const nyFormatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
timeZoneName: 'short',
timeStyle: 'long'
});
console.log(nyFormatter.format(date));
// "10:30:00 AM EDT"Custom Layouts with
formatToParts()
If you need to render localized date tokens inside custom HTML markup
or non-standard layouts, use formatToParts(). This method
returns an array of objects containing the token type and value.
const formatter = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric' });
const parts = formatter.formatToParts(date);
console.log(parts);
// [
// { type: 'month', value: 'May' },
// { type: 'literal', value: ' ' },
// { type: 'day', value: '15' }
// ]Performance Advantage
Creating an Intl.DateTimeFormat instance is
computationally heavier than formatting a single string. When formatting
multiple dates with the same configuration, create a single instance and
call .format() repeatedly rather than using
Date.prototype.toLocaleDateString(), which reconstructs the
internal formatter on every call.