Currently, there are multiple libraries to format dates in JavaScript. I used moment.js for a long time, but the bundle size was always a turn down for me. Then I switched to date-fns, which has a simple API and supports tree-shaking, and I have one project where I'm using luxon. They all work fine and have their use-cases, but in my opinion some times we end up bringing external libraries into our projects without really needing them, or without checking for a native approach first. I am guilty of that šŸ˜‰ but lately I've tried to always search for a native approach first, before bringing in a dependency, making sure to assess whether the bigger bundle size is worth it or not.

So, let's get into it. What I want to show you is a simple use case where we need to format dates differently depending on user locale. In Brazil, the most common date format is DD/MM/YYYY or DD/MM/YY where D = Day, M = Month and Y= Year. In the US, day and month switch places and sometimes you don't add the leading zero and in Germany, it's common to use dots instead of slashes as dividers (DD.MM.YYYY). To make sure we account for all these formats, we can leverage ECMAScript Internationalization API in our application.

Let me show you an example:

const myDate = new Date(2021, 10, 1);
let formatter = new Intl.DateTimeFormat('en-US');
console.log(formatter.format(myDate)) // "11/1/2021"

formatter = new Intl.DateTimeFormat('pt-BR');
console.log(formatter.format(myDate)) // "01/11/2021"

formatter = new Intl.DateTimeFormat('de-DE');
console.log(formatter.format(myDate)) // "1.11.2021"

You can also do it with a one-liner if you are not going to use the formatter later:

const myDate = new Date(2021, 10, 1);
console.log(new Intl.DateTimeFormat('pt-BR').format(myDate)) // "01/11/2021"

Now, instead of hard coding the language code, you can either use the user's preferred language (from the browser) or your the language the user set for your website:

const myDate = new Date(2021, 10, 1);
const langCode = document.documentElement.lang || navigator.language;
const formatter = new Intl.DateTimeFormat(langCode);
console.log(formatter.format(myDate)) // "01/11/2021"

You can also specify options for the date format:

const myDate = new Date(2021, 10, 1);
const formattedDate = new Intl.DateTimeFormat('en-US', {
    dateStyle: 'short',
    timeStyle: 'short'
}).format(myDate);
console.log(formattedDate) // "11/1/21, 12:00 AM"

const formattedDateMedium = new Intl.DateTimeFormat('en-US', {
    dateStyle: 'medium',
    timeStyle: 'medium'
}).format(myDate);
console.log(formattedDateMedium) // "Nov 1, 2021, 12:00:00 AM"

const formattedDateLong = new Intl.DateTimeFormat('en-US', {
    dateStyle: 'long',
    timeStyle: 'long'
}).format(myDate);
console.log(formattedDateLong) // "November 1, 2021 at 12:00:00 AM GMT-3"

const formattedDateFull = new Intl.DateTimeFormat('en-US', {
    dateStyle: 'full',
    timeStyle: 'full'
}).format(myDate);
console.log(formattedDateFull) // "Monday, November 1, 2021 at 12:00:00 AM Brasilia Standard Time"

The options are very flexible: you can set different formats for calendar, week, year (2-digit or numeric), month (numeric, 2-digit, long, short and narrow), weekday, wheter to use the 12-hour time, timezone. You can checkout the full list here.

I hope that after reading this post you will be better equipped to make a decision on whether or not you need an external library for handling date formatting. See you on the next post!