Sep 13 2018

We don't need Moment.js just to display dates and times anymore

Moment.js is a great library, but it’s still something extra for your users’ browsers to download, parse and run when they visit your site! Then, once you’ve downloaded all the code for all its myriad features, it’s often just turning an ISO date-time string from some API into the right timezone and format for the user. Fortunately we can do that, and do it better, with nothing but the features built in to modern browsers and IE 11!

Parsing ISO dates

In modern browsers and IE 9+, the Date constructor (as well as Date.parse()) supports a restricted subset of the ISO date format, with separators being mandatory. (For instance, 2017-04-26T19:30:00+09:30 works in browsers, but 20170426T193000+0930 doesn’t.) In practice, this restricted subset is exactly what most APIs will send, so the following Just Works:

const valueFromApi = "2017-04-26T19:30:00+09:30"
const myDate = new Date(valueFromApi)

Displaying to the user

This is where Moment.js used to shine. Way back when, all we got from the browser was Date.prototype.toDateString() and friends, which returned “a human readable form in American English”. In contrast, Moment.js has a comprehensive format string syntax that lets us mix and match date components whichever way we want. The built in Date object still doesn’t have anything like that, but modern browsers and IE 11 have something arguably better: Intl.DateTimeFormat. Here’s an example:

const longFmt = new Intl.DateTimeFormat(undefined, {
  weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
  hour: 'numeric', minute: 'numeric', timeZoneName: 'long'})
const shortFmt = new Intl.DateTimeFormat(undefined, {
  year: 'numeric', month: 'numeric', day: 'numeric',
  hour: 'numeric', minute: 'numeric'})
console.log(longFmt.format(myDate))
// Wednesday, 26 April 2017, 7:30 pm Australian Central Standard Time
// (on my system, yours will probably be different)
console.log(shortFmt.format(myDate))
// 26/04/2017, 7:30 pm

This lets you precisely control how dates are formatted—4- or 2-digit years, text or numeric months, omitting components, and so on—but still use the component ordering and separators your users are expecting, depending on the locale they chose when they first set up their computer or phone! (You can also specify a specific locale string like 'en-AU', or an IANA timezone to convert to like 'Australia/Adelaide', if you’re confident you know what the user wants to see better than the browser does.)

By changing your date display code to use Intl instead of Moment.js, you’re not only saving a few kilobytes of JS, but you’ll also show your users dates that are easier for them to read, wherever they are in the world.