cover-image

Replacing Moment.js with Alternatives

#javascript
#web

Andrew Vo-Nguyen

October 20, 2020

4 min read

In September Moment.js officially declared their project entered maintenance mode. This means that no further development would be done and that users should find an alternative.

As a user of Moment.js for the past year, I wasn't shocked that this news was coming. I had been reading some articles in passing and perhaps saw some comments on other GitHub packages on why Moment.js was such a terrible package. From what I had read:

  1. Moment is mutable. So running methods such as moment(currentDate).add(5, 'days'); would mutate currentDate instead of return a new date with the result. This is of course quite dangerous if you rely on currentDate being immutable and predictable. They do have a clone() method, however its usage is not forced.
  2. Moment does not support tree shaking which leads to large bundle sizes. I found this out the hard way when running Create React App's source map explorer on one of my university projects.

I remembered when I first tried Moment.js that it was so magical to manipulate JavaScript dates so easily. Dates are a pain to work with at the best of times and Moment.js just made my life that much easier. So how do I re-create this magic using a different package?

I googled some alternatives and tried day.js and then date-fns.

Day.js

Fast 2kB alternative to Moment.js with the same modern API

I am currently working on project where I am refactoring an older project to give it a new UI design and performance upgrades. Luckily, the project is still in its early stages so removing Moment.js wasn't such a big deal.

Day.js is a great direct replacement for Moment.js. Their chainable syntax is very familiar to Moment.js and it seems they have intentionally implemented it that way to help user migrate. Their .add() and .subtract() manipulations operate similarly, however the data is immutable. They use plugins for extra functionality such as time zone support, and you extend only what you need on the existing day.js object.

Example:

1var utc = require('dayjs/plugin/utc') // dependent on utc plugin
2var timezone = require('dayjs/plugin/timezone')
3dayjs.extend(utc)
4dayjs.extend(timezone)
5
6dayjs.tz("2014-06-01 12:00", "America/New_York")
7
8dayjs("2014-06-01 12:00").tz("America/New_York")
9
10dayjs.tz.guess()
11
12dayjs.tz.setDefault("America/New_York")

I really like how comprehensive and user friendly their documentation is on their website and with (at time of writing), 31,593 stars on GitHub, day.js is a great alternative for Moment.js.

I mentioned earlier that I am currently working a project and removing Moment.js from it. This project involves two other important packages. @material-ui/pickers and react-big-calendar. Both of these libraries used Moment.js to localize it's date data. Unfortunately neither of them support day.js. This was my only roadblock I had hit with day.js. So I tried date-fns...

date-fns

date-fns provides the most comprehensive, yet simple and consistent toolset for manipulating JavaScript dates in a browser & Node.js.

Now date-fns has a slightly steeper learning curve if you are migrating from Moment.js. It's formatting options differ from the the ones from Moment.js and day.js which use custom formatting rules. date-fns uses Unicode Technical Standard #35:

The syntax is a little different from Moment.js and day.js. It does not use chainable functions. I'll post a basic example to demonstrate:

1Import { format, formatDistance, formatRelative, subDays } from 'date-fns'
2
3format(new Date(), "'Today is a' iiii")
4//=> "Today is a Tuesday"
5
6formatDistance(subDays(new Date(), 3), new Date())
7//=> "3 days ago"
8
9formatRelative(subDays(new Date(), 3), new Date())
10//=> "last Friday at 7:26 p.m."

At the current time of writing, date-fns has 23,934 tars on GitHub making it, in my eyes a highly popular replacement for Moment.js. I so far have not hit any roadblocks using date-fns and have found a function to satisfy all my magical date manipulation requirements...including handling different time zones.

I hope this post helps you migrate away from Moment.js. As great as Moment.js was for JavaScript, it is time to move on. There is also a great eslint plugin to help you identify instances of Moment.js in your project. It is called eslint-plugin-you-dont-need-momentjs. Link below: