Back to Blog
JavaScriptIntlDateTimeFormati18n

JavaScript Intl.DateTimeFormat Guide

Master JavaScript Intl.DateTimeFormat for locale-aware date and time formatting.

B
Bootspring Team
Engineering
December 30, 2018
6 min read

Intl.DateTimeFormat provides locale-aware date and time formatting. Here's how to use it effectively.

Basic Usage#

1const date = new Date('2024-03-15T14:30:00'); 2 3// Default locale 4const formatter = new Intl.DateTimeFormat(); 5console.log(formatter.format(date)); // '3/15/2024' (US) 6 7// Specific locale 8const germanFormatter = new Intl.DateTimeFormat('de-DE'); 9console.log(germanFormatter.format(date)); // '15.3.2024' 10 11const japaneseFormatter = new Intl.DateTimeFormat('ja-JP'); 12console.log(japaneseFormatter.format(date)); // '2024/3/15'

Date Styles#

1const date = new Date('2024-03-15T14:30:00'); 2 3// Full date 4new Intl.DateTimeFormat('en-US', { dateStyle: 'full' }) 5 .format(date); // 'Friday, March 15, 2024' 6 7// Long date 8new Intl.DateTimeFormat('en-US', { dateStyle: 'long' }) 9 .format(date); // 'March 15, 2024' 10 11// Medium date 12new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }) 13 .format(date); // 'Mar 15, 2024' 14 15// Short date 16new Intl.DateTimeFormat('en-US', { dateStyle: 'short' }) 17 .format(date); // '3/15/24'

Time Styles#

1const date = new Date('2024-03-15T14:30:45'); 2 3// Full time 4new Intl.DateTimeFormat('en-US', { timeStyle: 'full' }) 5 .format(date); // '2:30:45 PM Eastern Daylight Time' 6 7// Long time 8new Intl.DateTimeFormat('en-US', { timeStyle: 'long' }) 9 .format(date); // '2:30:45 PM EDT' 10 11// Medium time 12new Intl.DateTimeFormat('en-US', { timeStyle: 'medium' }) 13 .format(date); // '2:30:45 PM' 14 15// Short time 16new Intl.DateTimeFormat('en-US', { timeStyle: 'short' }) 17 .format(date); // '2:30 PM'

Combined Styles#

1const date = new Date('2024-03-15T14:30:00'); 2 3// Date and time 4new Intl.DateTimeFormat('en-US', { 5 dateStyle: 'full', 6 timeStyle: 'short', 7}).format(date); // 'Friday, March 15, 2024 at 2:30 PM' 8 9new Intl.DateTimeFormat('en-US', { 10 dateStyle: 'medium', 11 timeStyle: 'medium', 12}).format(date); // 'Mar 15, 2024, 2:30:00 PM'

Custom Components#

1const date = new Date('2024-03-15T14:30:00'); 2 3// Custom format 4new Intl.DateTimeFormat('en-US', { 5 weekday: 'long', 6 year: 'numeric', 7 month: 'long', 8 day: 'numeric', 9}).format(date); // 'Friday, March 15, 2024' 10 11// Time components 12new Intl.DateTimeFormat('en-US', { 13 hour: '2-digit', 14 minute: '2-digit', 15 second: '2-digit', 16 hour12: true, 17}).format(date); // '02:30:00 PM' 18 19// 24-hour format 20new Intl.DateTimeFormat('en-US', { 21 hour: '2-digit', 22 minute: '2-digit', 23 hour12: false, 24}).format(date); // '14:30'

Component Options#

1const date = new Date('2024-03-15T14:30:00'); 2 3// Weekday options: 'long', 'short', 'narrow' 4console.log(new Intl.DateTimeFormat('en-US', { weekday: 'long' }).format(date)); // 'Friday' 5console.log(new Intl.DateTimeFormat('en-US', { weekday: 'short' }).format(date)); // 'Fri' 6console.log(new Intl.DateTimeFormat('en-US', { weekday: 'narrow' }).format(date)); // 'F' 7 8// Month options: 'long', 'short', 'narrow', 'numeric', '2-digit' 9console.log(new Intl.DateTimeFormat('en-US', { month: 'long' }).format(date)); // 'March' 10console.log(new Intl.DateTimeFormat('en-US', { month: 'short' }).format(date)); // 'Mar' 11console.log(new Intl.DateTimeFormat('en-US', { month: 'narrow' }).format(date)); // 'M' 12console.log(new Intl.DateTimeFormat('en-US', { month: 'numeric' }).format(date)); // '3' 13console.log(new Intl.DateTimeFormat('en-US', { month: '2-digit' }).format(date)); // '03' 14 15// Day options: 'numeric', '2-digit' 16console.log(new Intl.DateTimeFormat('en-US', { day: 'numeric' }).format(date)); // '15' 17console.log(new Intl.DateTimeFormat('en-US', { day: '2-digit' }).format(date)); // '15' 18 19// Year options: 'numeric', '2-digit' 20console.log(new Intl.DateTimeFormat('en-US', { year: 'numeric' }).format(date)); // '2024' 21console.log(new Intl.DateTimeFormat('en-US', { year: '2-digit' }).format(date)); // '24'

Time Zones#

1const date = new Date('2024-03-15T14:30:00Z'); 2 3// Different time zones 4const formatter = (tz) => 5 new Intl.DateTimeFormat('en-US', { 6 timeStyle: 'long', 7 timeZone: tz, 8 }); 9 10console.log(formatter('America/New_York').format(date)); // '10:30:00 AM EDT' 11console.log(formatter('America/Los_Angeles').format(date)); // '7:30:00 AM PDT' 12console.log(formatter('Europe/London').format(date)); // '2:30:00 PM GMT' 13console.log(formatter('Asia/Tokyo').format(date)); // '11:30:00 PM JST' 14 15// Display time zone name 16new Intl.DateTimeFormat('en-US', { 17 timeZone: 'America/New_York', 18 timeZoneName: 'short', // 'long', 'shortOffset', 'longOffset' 19}).format(date); // '3/15/2024, EDT'

Format Parts#

1const date = new Date('2024-03-15T14:30:00'); 2 3const formatter = new Intl.DateTimeFormat('en-US', { 4 dateStyle: 'full', 5 timeStyle: 'short', 6}); 7 8// Get individual parts 9const parts = formatter.formatToParts(date); 10console.log(parts); 11// [ 12// { type: 'weekday', value: 'Friday' }, 13// { type: 'literal', value: ', ' }, 14// { type: 'month', value: 'March' }, 15// { type: 'literal', value: ' ' }, 16// { type: 'day', value: '15' }, 17// { type: 'literal', value: ', ' }, 18// { type: 'year', value: '2024' }, 19// { type: 'literal', value: ' at ' }, 20// { type: 'hour', value: '2' }, 21// { type: 'literal', value: ':' }, 22// { type: 'minute', value: '30' }, 23// { type: 'literal', value: ' ' }, 24// { type: 'dayPeriod', value: 'PM' } 25// ] 26 27// Custom formatting using parts 28function customFormat(date) { 29 const parts = formatter.formatToParts(date); 30 const values = {}; 31 parts.forEach(({ type, value }) => { 32 values[type] = value; 33 }); 34 return `${values.month} ${values.day}, ${values.year}`; 35}

Range Formatting#

1const start = new Date('2024-03-15T09:00:00'); 2const end = new Date('2024-03-15T17:00:00'); 3 4const formatter = new Intl.DateTimeFormat('en-US', { 5 hour: 'numeric', 6 minute: '2-digit', 7}); 8 9// Format range 10console.log(formatter.formatRange(start, end)); 11// '9:00 AM – 5:00 PM' 12 13// Different days 14const multiDay = new Intl.DateTimeFormat('en-US', { 15 month: 'short', 16 day: 'numeric', 17}); 18 19const startDate = new Date('2024-03-15'); 20const endDate = new Date('2024-03-20'); 21console.log(multiDay.formatRange(startDate, endDate)); 22// 'Mar 15 – 20'

Calendar Systems#

1const date = new Date('2024-03-15'); 2 3// Different calendars 4const calendars = ['gregory', 'chinese', 'hebrew', 'islamic', 'japanese']; 5 6calendars.forEach(calendar => { 7 const formatted = new Intl.DateTimeFormat('en-US', { 8 calendar, 9 dateStyle: 'full', 10 }).format(date); 11 console.log(`${calendar}: ${formatted}`); 12}); 13 14// Japanese with era 15new Intl.DateTimeFormat('ja-JP-u-ca-japanese', { 16 era: 'long', 17 year: 'numeric', 18 month: 'long', 19 day: 'numeric', 20}).format(date); // '令和6年3月15日'

Numbering Systems#

1const date = new Date('2024-03-15'); 2 3// Arabic numerals 4new Intl.DateTimeFormat('ar-EG', { 5 dateStyle: 'short', 6}).format(date); // '١٥/٣/٢٠٢٤' 7 8// Thai numerals 9new Intl.DateTimeFormat('th-TH-u-nu-thai', { 10 dateStyle: 'short', 11}).format(date); // '๑๕/๓/๖๗'

Practical Utilities#

1// Reusable date formatter factory 2function createDateFormatter(options = {}) { 3 const { 4 locale = navigator.language, 5 ...formatOptions 6 } = options; 7 8 const formatter = new Intl.DateTimeFormat(locale, formatOptions); 9 10 return { 11 format: (date) => formatter.format(date), 12 formatRange: (start, end) => formatter.formatRange(start, end), 13 formatParts: (date) => formatter.formatToParts(date), 14 }; 15} 16 17// Common formatters 18const formatters = { 19 date: createDateFormatter({ dateStyle: 'medium' }), 20 time: createDateFormatter({ timeStyle: 'short' }), 21 dateTime: createDateFormatter({ dateStyle: 'medium', timeStyle: 'short' }), 22 relative: createDateFormatter({ 23 weekday: 'long', 24 month: 'long', 25 day: 'numeric', 26 }), 27}; 28 29// Usage 30const now = new Date(); 31console.log(formatters.date.format(now)); 32console.log(formatters.time.format(now));

Performance Caching#

1// Cache formatters for reuse 2const formatterCache = new Map(); 3 4function getFormatter(locale, options) { 5 const key = `${locale}-${JSON.stringify(options)}`; 6 7 if (!formatterCache.has(key)) { 8 formatterCache.set(key, new Intl.DateTimeFormat(locale, options)); 9 } 10 11 return formatterCache.get(key); 12} 13 14// Usage - formatter is cached 15const formatted1 = getFormatter('en-US', { dateStyle: 'long' }).format(new Date()); 16const formatted2 = getFormatter('en-US', { dateStyle: 'long' }).format(new Date());

Best Practices#

Locale Selection: ✓ Use user's locale when possible ✓ Fall back gracefully ✓ Test with multiple locales ✓ Consider regional variants Formatting: ✓ Use dateStyle/timeStyle for consistency ✓ Cache formatter instances ✓ Use formatToParts for custom layouts ✓ Handle time zones explicitly Performance: ✓ Reuse formatter instances ✓ Create formatters outside loops ✓ Cache by locale + options ✓ Use formatRange for intervals Avoid: ✗ Creating formatters repeatedly ✗ Ignoring time zones ✗ Hardcoding date formats ✗ Assuming locale behavior

Conclusion#

Intl.DateTimeFormat provides powerful, locale-aware date formatting. Use dateStyle and timeStyle for consistent formatting, handle time zones explicitly with the timeZone option, and cache formatter instances for performance. The formatToParts method enables custom formatting while respecting locale conventions.

Share this article

Help spread the word about Bootspring