SoatDev IT Consulting
SoatDev IT Consulting
  • About us
  • Expertise
  • Services
  • How it works
  • Contact Us
  • News
  • July 9, 2023
  • Rss Fetcher
Image generated with canva.com

Moment.js, a widely recognized date manipulation library, has been in legacy mode for almost three years now, starting from September 2020. However, it’s still slightly more used than its popular competitors such as dayjs and date-fns, at least according to npm stats (~17M weekly downloads vs ~14M for each of the competitors). Hence, there is a decent chance that you, my dear reader, are using it too.

Moment.js is in maintenance mode due to a variety of reasons. Some of them were described by the authors themselves, and some are well known to the community such as the notorious “why the hell are the moment locales in my bundle and how do I remove them”. Also, a lot of people have encountered issues with slow functions like isSameOrBefore().

However, there’s definitely more!

Let’s say, we fetch an array of Employee objects that, among other things, contains several stringified dates in DD-MM-YYYY format:

const sampleEmployee: Employee = { 
versionId: '01-01-2023',
startDate: '01-01-2020',
termDate: '01-01-2024'
};

Now we might want to do something with those dates. Like, in this case, calculate the length of the contract. Or anything else. Whatever.

The thing that matters is that we can’t perform any date calculation with strings, so we need to instantiate a Date object — which is absolutely straightforward.

But if we’re already using Moment.js, there’s a good chance that there is already a bunch of helper functions ( thousands of lines in utils.ts, I’m looking at you!) that we want to use, for example, to properly handle date granularity. Or at least for consistency.

Now, we aren’t dealing with just one object, we have an array of them. Regardless of our task, if there is any date logic, we’re going to create a moment object on every iteration of the loop, probably with a helper function of some sort, but in this example let’s use moment directly for simplicity.

We know that moment constructor is really smart and can instantiate a valid object from pretty much everything that resembles a date, so the code would look like this:

const mock = { versionId: '01-01-2020', termDate: '02-01-2021', startDate: '03-01-2020' };
const mockData = Array(10000).fill(mock);

const result = mockData.map(item => {
const versionId = moment(item.versionId);
const startDate = moment(item.startDate);
const termDate = moment(item.termDate);

// It doesn't really matter what we do with the dates. Just return them:
return { versionId, startDate, termDate };
});

Let’s test this code on a modern laptop, but with 4x CPU slowdown to emulate a slower device:

The result is… disappointing

We spend a good 1/3 of a second iterating through the loop and creating 3-moment objects on each iteration. We didn’t even calculate anything in this loop yet, but it’s already fairly slow. But why?

It turns out that the Moment constructor is slower when it’s using a string date instead of a Date object!

I have created a benchmark to prove this hypothesis, and it shows that even with the overhead of creating a native Date object, it’s almost twice as fast in comparison with the direct usage of a string:

Benchmark created using measurethat.net

Let’s test it directly with the CPU slowdown:

  const result = mockData.map(item => {
const versionId = moment(new Date(item.versionId));
const startDate = moment(new Date(item.startDate));
const termDate = moment(new Date(item.termDate));

return { versionId, startDate, termDate };
});
Not twice as fast in reality, but 120ms faster anyway

Now, it’s understandable that there might be a lot of logic in the codebase that’s already written using moment.js.

There might be no development resources to replace it right away. If this is the case, this is already a good improvement. However, if there is a possibility to replace it, the speed can be improved even more if a native Date is used.

Yes, the native Date API is still clunky. And here is where date-fns truly shines, because it’s using native Date objects. Therefore, if we need to do something with our dates such as to calculate the difference, no custom objects will be created, saving the runtime.

Let’s run the test again, but this time we’ll only create the Date objects:

  const result = mockData.map(item => {
const versionId = new Date(item.versionId);
const startDate = new Date(item.startDate);
const termDate = new Date(item.termDate);

return { versionId, startDate, termDate };
});

Now this is three times faster than the original version. Quite nice, isn’t it?

A small post-scriptum: when working with dates in the loops, it’s sometimes a really good idea to memoize utility functions. It depends on the data you’re dealing with, but there is a good chance that the dates might be repeated over and over in different objects. Therefore, if there is a way to not repeat the calculations — take advantage of it, it might save few more precious milliseconds, resulting in an improved user experience.


(Yet) Another Way to Harm Performance With Moment.js was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.

Previous Post
Next Post

Recent Posts

  • Grammarly secures $1B in non-dilutive funding from General Catalyst
  • Top 30 startups announced for VivaTech 2025 Innovation of the Year Award
  • Elon Musk sure does want everyone to think he’s leaving politics
  • Netflix’s series about the FTX fiasco has found its leading effective altruists
  • Inside the AI revolution: Top insights and breakthroughs from our partners at TechCrunch Sessions: AI

Categories

  • Industry News
  • Programming
  • RSS Fetched Articles
  • Uncategorized

Archives

  • May 2025
  • April 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023

Tap into the power of Microservices, MVC Architecture, Cloud, Containers, UML, and Scrum methodologies to bolster your project planning, execution, and application development processes.

Solutions

  • IT Consultation
  • Agile Transformation
  • Software Development
  • DevOps & CI/CD

Regions Covered

  • Montreal
  • New York
  • Paris
  • Mauritius
  • Abidjan
  • Dakar

Subscribe to Newsletter

Join our monthly newsletter subscribers to get the latest news and insights.

© Copyright 2023. All Rights Reserved by Soatdev IT Consulting Inc.