Moving Away from Moment.js
A few years ago, Moment.js updated its docs with a Project Status, which more or less discourages the use of the package going forward. Moment.js offers a handful of alternatives, and our team considered a few of those.
The team decided we wanted to investigate the pros and cons of three Moment.js alternatives—Luxon, date-fns, and Day.js. The spike involved comparing package sizes, skimming documentation, and estimating the cost-benefit analysis of each.
Here’s a visual overview of an analysis of the package sizes and download speed:
Why We Chose Day.js
Day.js started to look really appealing, given these results. We began to look into its features, usage, and advantages and found the following:
Syntactically Similar to Moment.js
Since Day.js and Moment have similar syntax, refactoring existing code was likely to be less painful than if we chose an alternative. Many of the operations are a one-to-one replacement from Moment.js to Day.js. Take the following code snippets, which use the
format() method to transform either a Moment.js or Day.js object into a readable string:
moment().format("MM-DD-YYYY HH:mm:ss a")
dayjs().format("MM-DD-YYYY HH:mm:ss a")
Parsing methods like
endof() are also identical in both libraries, as are the manipulation methods
.add() and .
Tree-shaking via Plugins
One of the significant differences between Moment.js and Day.js is that the latter requires you to import and extend plugins to utilize certain features. This is a key reason why Day.js is so lightweight. A project will only bundle the plugins that are used.
Support for Internationalization
Day.js offers internationalization (i18n) support as well via the
localeData plugin. This evolving plugin provides useful features such as the ability to list out translated date/time strings like months in a specified location’s language:
const dayjs = require("dayjs"); require("dayjs/locale/es-mx") const localeData = require("dayjs/plugin/localeData") dayjs.extend(localeData) const instance = dayjs().locale("es-mx") const months = instance.localeData().months() console.log("months: ", months) // months: [ // 'enero', 'febrero', // 'marzo', 'abril', // 'mayo', 'junio', // 'julio', 'agosto', // 'septiembre', 'octubre', // 'noviembre', 'diciembre' // ]
Finally, one of the reasons our team decided to use a datetime library in the first place was due to some necessary manipulation of timezones in the server of our application. Imagine a database that stores all datetimes in UTC time but an interface that displays said datetime in the user’s timezone. To handle something like that in Moment.js, we had to install an additional library called moment-timezone. Day.js includes timezone manipulation support as-is.
Day.js will parse time in local time by default. So for a machine set to US/Pacific time, all Day.js objects will display in the Pacific timezone. The
utc plugin offers a way to convert these objects to Coordinated Universal Time, which in our case, was how we wanted to store them in the database. Here’s an example from a machine in US/Pacific time:
const dayjs = require("dayjs"); const utc = require('dayjs/plugin/utc') dayjs.extend(utc) const pacificTimestamp = dayjs(new Date("January 1, 2023")).format("MM-DD-YY hh:mm a") console.log(pacificTimestamp) // prints "01-01-23 00:00 am" const utcTimestamp = dayjs(pacificTimestamp).utc().format("MM-DD-YY hh:mm a") console.log(utcTimestamp) // prints "01-01-23 08:00 am"
timezone plugin and
.tz() method offers further support for displaying dates in different locales. Take the following, which displays a date in the computer’s timezone (Pacific) and converts it to Eastern time.
const dayjs = require("dayjs") const timezone = require("dayjs/plugin/timezone") dayjs.extend(timezone) const utc = require('dayjs/plugin/utc') dayjs.extend(utc) const pst = dayjs().format("MM-DD-YYYY h:mm a") console.log(pst) // 01-01-2023 12:00 am const est = dayjs.tz(dayjs(pst), "America/Toronto").format("MM-DD-YYYY h:mm a") console.log(est) // 01-01-2023 3:00 am
In summary, Day.js is a solid choice for projects needing the convenience and support of a datetime library, particularly if looking to replace Moment.js. It offers a lot of the same features in a smaller package, and its syntax will be familiar to teams already using Moment.js.
Do you think Day.js is a good alternative to Moment?