Adding working dates to your application always seems like an easy task in theory, until you attempt to do it. There is always something getting in the way, whether it’s a time zone problem when trying to internationalize your website, issues showing the date in the needed format, or even trying to do some basic arithmetic with them (i.e subtracting three days from a date, it shouldn’t be that hard, should it?).
The problem is that, sadly, JavaScript is not really prepared to natively deal with dates. Which is a bit ironic considering it does have a Date object we can use for some basic operations.
What do I mean then, when I say JavaScript is not ready? I mean that the API for this object is not rich enough for our daily needs, it doesn’t have the high-level support you’d expect from such an object to take on problems such as internationalization, timezone support and so on.
Here is where the libraries I’m going to be reviewing come into play. These seven date libraries add layers of abstraction on top of JavaScript’s Date object and make it actually useful.
Reviewed version: 2.24.0
Moment.js is one of the oldest and best known date-related libraries for both, Node.js and vanilla JavaScript (making it browser compatible). And because of this, they’ve had the time to make it compatible with many of the most common web-development utilities, such as:
It offers a great API without having to modify the Date object’s original prototype, instead, they created a wrapper object around it, making sure they don’t pollute the original namespace.
As a quick example, here is how you’d set up the current date. Add seven days, then subtract a month, and finally set the year and time values. All in a single line of easy-to-read code, like this:
moment().add(7, 'days').subtract(1, 'months').year(2009).hours(0).minutes(0).seconds(0);
They support over 20 different locales, so if you’re aiming at solving your internationalization problems, moment.js is a good bet.
A good measure of the success and overall utility of a particular library is by checking out the plugin/extension ecosystem that exists around it. In the case of moment.js, there are 22 officially supported ones. That might not be a big number at first glance, but if you consider that all these libraries were designed around a single object, the Date object, then having over 20 plugins is definitely a great sign.
You can find their entire list of plugins on their documentation page, but some of the most interesting out there are:
This one allows you to format your dates and times just like Twitter does (notice how they abbreviate their time ago-like dates with a single letter when it’s clear enough, such as 1h for “1 hour ago” or 2d for “2 days ago”).
With this plugin you can simply do something like:
moment().subtract(6, 'days').twitterShort();
To return “6d”.
How many times did you write the date format when trying to display your dates in one specific way? Something like YYYY-MM-dd or similar variations. But always manually, we write it, and then the library formats the date accordingly.
This plugin, instead of formatting the date, parses a date string and returns the actual format for you to re-use.
So you can do something like:
var format = moment.parseFormat('Thursday, February 6th, 2014 9:20pm'); // format will contain: dddd, MMMM Do, YYYY h:mma
This particular plugin is great for adding dynamic behavior to your formatting logic, for example, making the formatting dynamic and allowing your users to enter a date example, instead of having them learn how to configure their own format.
This one is actually a full re-write of JavaScript’s setTimeInterval and setTimeout functions, allowing you to mix moment’s syntax and create a much more powerful timer.
You can do something like this:
var timer = moment.duration(5, "seconds").timer({loop: true}, function() { // Callback });
Which is already a lot easier to read and understand than:
setInterval(function() { //Callback }, 5000)
Again, there are over 20 plugins, I invite you to check out their documentation page and review the list for yourself.
Reviewed version: 2
Advertised as the lodash of date libraries, date-fns tries to provide a better experience than the one Moment.js is able to give.
It’s API is quite extensive with over 140 different time-related functions, their creators and contributors hope to make you switch from using Moment and get hooked into their own solution to time management.
Some of the key aspects of this library are:
Let’s quickly run through some code samples to give you an idea of what makes this library unique.
const { addYears, formatWithOptions } = require('date-fns/fp') const { es } = require('date-fns/locale') const addFiveYears = addYears(5) const dateToString = formatWithOptions({ locale: es }, 'd MMMM yyyy') const dates = [ new Date(2017, 0, 1), new Date(2017, 1, 11), new Date(2017, 6, 2) ] const toUpper = arg => String(arg).toUpperCase() const formattedDates = dates.map(addFiveYears).map(dateToString).map(toUpper) //=> ['1 ENERO 2022', '11 FEBRERO 2022', '2 JULIO 2022']
This example shows two of the points I made above: the functions-per-file mechanics, allowing you to only require the bits you actually need (both imports take advantage of that in the example) and the functional programming helper functions. Notice how with those two imported functions (addYears
and formatWithOptions
) we’re composing the entire process in the final line (those two and the toUpper
anonymous function as well).
A quick note about the code: Even though it’s the same example as the one shown on the library’s homepage, I had to adapt it to be compatible with Node.js.
Reviewed version: 1.16.1
Luxon is a very interesting project because if you look at it’s URL, it lives under the Moment.js project, so why is it there? You can read the whole story from the author himself, but the main gist of it is that it attempts to be a better version of Moment, however:
One of the main differences in Luxon when compared to it’s predecessor (if we can call Moment.js that), is that this time around, all objects are immutable (notice a pattern here? One could argue Moment.js made a poor decision making their objects mutable and everyone in the community went out of their way to fix that problem).
var m1 = moment(); var m2 = m1.add(1, 'hours'); m1.valueOf() === m2.valueOf(); //=> true var d1 = DateTime.local(); var d2 = d1.plus({ hours: 1 }); d1.valueOf() === d2.valueOf(); //=> false
In the above example you can see this difference in action, while with Moment.js (first example), you’d run into that kind of “problem” (the quotes are there because the problem only happens if you’re not paying attention) since the add
method would mutate m1
instead of returning the new value on m2
, the API from Luxon would prevent you from having that problem since plus
returns a new object on d2
instead of modifying d1
.
The other big difference with Moment.js is the fact that internationalization is based on the Intl API from browsers. Essentially, what this means is:
There are other changes that might be of interest to you if you’re a Moment.js user, so make sure to check them out on their documentation.
Reviewed version: 1.8.14
DayJS attempts to be a minified version of Moment.js (are we seeing the patterns here, people?). There is something to be said for a library that claims to have the same API of Moment.js and reduce its file size by 97%. That’s right, where Moment.js full minified file weights a total of 67,9Kb, DayJS minified file is only 2Kb. That’s crazy and yet they have support for internationalization, plugins and everything else.
You can think of DayJS as lodash when everyone was using underscore (remember?). Suddenly lodash came into the picture boosting a similar claim, they had a very similar API with a reduced footprint, winning the hearts of many front-end developers who, as I mentioned above, are always trying to save as many bytes as possible to reduce loading times.
And just like Moment.js, this library has around 20 plugins officially supported which you can check out on their documentation.
Finally, while this library appears to be everything it claims to be and developers are starting to adopt it as seen in the following download trends chart:
MomentJS is still rocking the monthly downloads, since it’s been around for 8+ years (compared to the 1+ year of DayJS). It’ll take some time, but if MomentJS doesn’t adapt (maybe Luxon could be an option?) it’ll eventually be replaced by this new kid on the block.
There is no point in showing code samples since the API is practically the same as MomentJS, just check their official documentation if you need anything in particular and switch to DayJS if you’re worried about loading times and data usage (a big problem for mobile web developers).
Reviewed version: 2.1.2
To change things up a bit, this next library was not created as a replacement for MomentJS (I know, shocking!) but instead, it only has one job, and it does so very well.
The objective of MS is to convert any kind of date format into milliseconds and back.
This is a very narrow use case, I know, but as you very well know, turning dates into milliseconds has its advantages, especially if you’re trying to do things like comparison, and some forms of arithmetic operations (it’s a lot easier to add 1000 milliseconds to a number, than saying you need to add 1 second to a Date object).
So in other words, with this library you can do things like this:
ms('2 days') // 172800000 ms('1d') // 86400000 ms('10h') // 36000000 ms('2.5 hrs') // 9000000 ms('2h') // 7200000 ms('1m') // 60000 ms('5s') // 5000 ms(60000) // "1m" ms(2 * 60000) // "2m" ms(-3 * 60000) // "-3m"
Now, I know what you’re thinking, why? Who’s using it? Well, given the fact that this library has over 30 million downloads every week, I’d say it covers a very specific and yet, common use case. So consider checking it out if this is all you need for your time-related logic.
Reviewed version: 1.11.0
Yet another general time management library aiming at replacing MomentJS and others from the above list. It tries to differ from others like MomentJS by avoiding the same wrapper around the Date object technique and instead, it implements the entire logic from scratch.
Is that better? The jury is still out on that one, it probably gives the maintainers more room to play around with basic concepts and twist them in ways the Date object can’t go. That being said, this library is marginally smaller than MomentJS (sitting at around 40Kb) far away from the tiny 2Kb of DayJS.
It does, however, provide immutability (shocking) and domain-specific classes, helping you, the developer, write cleaner OOP code.
A very interesting feature of js-joda is the extensibility it provides. As immutable objects don’t really have setters, this library provides the with
method, which returns a new object with the new value set. And if instead of setting it a value, you set it a special object, you can extend the way you get values.
Let me show you:
// implement a TemporalAdjuster that returns the next or same even day of month var nextOrSameEvenDay = { adjustInto: function(t) { return t.dayOfMonth() % 2 === 0 ? t : t.plusDays(1); } }; LocalDateTime.parse("2012-12-23T12:00").with(nextOrSameEvenDay); // '2012-12-24T12:00' LocalDate.parse("2012-12-24").with(nextOrSameEvenDay); // '2012-12-24'
Basically, we’re parsing a date string (nothing fancy there), and then with the custom object (notice the special adjustInto
method) we’re adding a very random behavior, but valid none the less.
I would personally recommend this library if you’re looking for this type of flexibility, otherwise, I’ve already covered better ones above.
Reviewed version: 5.9.0
I couldn’t leave out a time library called Spacetime, sorry, but my nerdy side won that battle. That being said, this one has a very interesting focused: timezones.
Yes, it provides a MomentJS-like API, with immutable objects (yawn!) too, but the main focus of this library is to help you deal with timezones easily. And remember, timezones tend to be one of the main issues when dealing with any type of internationalization development, so already this looks promising.
Let me show you some code:
const spacetime = require('spacetime') let d = spacetime('March 1 2012', 'America/New_York') //set the time d = d.time('4:20pm') console.log(d.time()) d = d.goto('America/Los_Angeles') console.log(d.time()) //'1:20pm'
That was super easy, wasn’t it? A note about Spacetime though, is that it doesn’t rely on the Intl API like Luxon did, so the library itself is not really lightweight sitting at around 40Kb. That being said, timezones still follow the IANA naming convention, which is great for standardizing your code.
Another cool thing about our last library is that it can observe daylight saving times where applicable, so the following happens:
d = d.goto('Eastern Time') // "America/New_York" d = d.goto('PST') // automatically becomes 'PDT' in the summer
There are other nifty methods such as season
which returns the current season for a particular date (either summer/winter/spring/fall is returned) as well as hasDST
and inDST
which return whether a timezone ever uses daylight saving times and if it has it active at the particular date/time configuration.
Finally, extending Spacetime is quite straightforward, which helps add extra features, such as:
spacetime.extend({ isHappyHour: function() { return this.hour() === 16 } }) d = d.time('4:15pm') console.log(d.isHappyHour()) //true
These were 7 of the most common JavaScript libraries that deal with date and time. Given the existing information and the usage data available online, if you’re having to deal with very complex date-time related features my recommendations would be going with either MomentJS because it’s a classic and time tested library, or simply try the brand new and faster model: DayJS, same API, better object management and all-around smaller footprint.
If on the other hand, you have very specific needs, think about going with ms or Spacetime.
Which libraries are you using now? Did I miss yours? Leave a comment below and let us know!
See you on the next one!
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
4 Replies to "The 7 best JavaScript date libraries"
Awesome summary. I was convinced to try date-fns over moment. I just wish you had mentioned here (since date-fns does not, at the time, in their documentation) that if you want to use it in a browser, you must use a bundler to build the .js file yourself. Due to time constraints, it is no longer available on a CDN or for download.
Sorry I missed that part! But thanks for sharing your findings here, it’ll help others in the future, I’m sure of it!
Looks like moment js is going away. https://momentjs.com/docs/
Moment is not immutable https://momentjs.com/guides/#/lib-concepts/mutability/ and it’s in their documentation since a very long time ago. Another thing in their documentation is that they don’t recommend their library anymore. Chrome dev tools recommend not using it for its bundle size alone. Please, update this article, it’s very misleading to have momentjs in the top like a “clear winner” or “because it’s the most known”.