Format a Date Range with Intl.DateTimeFormat
To format a date range, use formatter.formatRange(start, end) — it collapses shared fields ('Mar 3 - 5, 2024') and uses the locale's range separator. Part of Mastering Intl.DateTimeFormat Options.
Why this scenario is tricky
Concatenating two formatted dates with a hyphen ('Mar 3, 2024' + ' - ' + 'Mar 5, 2024') is verbose and wrong in most locales: it repeats the shared month and year and uses the wrong dash. formatRange knows to collapse common parts and pick the locale's range dash.
Minimal working solution
const fmt = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
fmt.formatRange(new Date('2024-03-03'), new Date('2024-03-05')); // 'Mar 3 - 5, 2024'
Full production version
// Cache the formatter; formatRangeToParts gives you the pieces for custom markup.
const fmt = new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium' });
const parts = fmt.formatRangeToParts(new Date('2024-03-03'), new Date('2024-03-05'));
// each part is tagged source: 'startRange' | 'endRange' | 'shared'
Verification snippet
Common pitfalls
Frequently Asked Questions
How do I format a date range in JavaScript?
Build an Intl.DateTimeFormat and call formatRange(startDate, endDate). It collapses fields the two dates share — printing 'Mar 3 - 5, 2024' instead of repeating the month and year — and uses the correct range separator for the locale.
How do I customize the markup of a formatted range?
Use formatRangeToParts(start, end). It returns an array of tokens, each tagged with a source of startRange, endRange, or shared, so you can wrap the start and end portions in your own elements while keeping locale-correct text.