You don't (may not) need Moment.js
Moment.js is a fantastic time & date library with lots of great features and utilities. However, if you are working on a performance sensitive web application, it might cause a huge performance overhead because of its complex APIs and large bundle size.
Problems with Moment.js:
- It is highly based on OOP APIs, which makes it fail to work with tree-shaking, thus leading to a huge bundle size and performance issues.
- It is mutable and it causes bugs:
- Complex OOP API (which doubles mutability problem). Here is an example:
https://github.com/moment/moment/blob/develop/src/test/moment/add_subtract.js#L244-L286
Moment.js allows to use
a.subtract('ms', 50)
,a.subtract(50, 'ms')
and evena.subtract('s', '50')
.
If you are not using timezone but only a few simple functions from moment.js, this might bloat your app, and therefore is considered overkill. dayjs has a smaller core and has very similar APIs so it makes it very easy to migrate. date-fns enables tree-shaking and other benefits so that it works great with React, Sinon.js, and webpack, etc. See https://github.com/moment/moment/issues/2373 for more ideas on why and how people switch from moment.js to other solutions.
Brief Comparison
Name | Tree-shaking | Methods richness | Pattern | Locale | Timezone Support | Popularity (stars) | Sizes |
---|---|---|---|---|---|---|---|
Moment.js | No | High | OO | 123 | Good (moment-timezone) | ||
Luxon | No | High | OO | - | Good (Intl) | ||
date-fns | Yes | High | Functional | 64 | Good (date-fns-tz) | ||
dayjs | No | High | OO | 138 | Good (Intl) |
Voice of Developers
Removed moment.js to replace with date-fns - build output reduced by 40%
—Jared Farago from webnode project.
Good library if you’re looking to replace Moment.js for one reason or another. Immutable too.
—Dan Abramov, Author of Redux and co-author of Create React App. Building tools for humans.
—Matija Marohnić, a design-savvy frontend developer from Croatia.
ESLint Plugin
If you're using ESLint, you can install a plugin that will help you identify places in your codebase where you don't (may not) need Moment.js.
Install the plugin...
npm install --save-dev eslint-plugin-you-dont-need-momentjs
...then update your config
"extends" : ["plugin:you-dont-need-momentjs/recommended"],
Quick Links
- Millisecond/Second/Minute/Hour
- Date of Month
- Day of Week
- Day of Year
- Week of Year
- Days in Month
- Weeks in Year
- Maximum of the given dates
- Minimum of the given dates
Feature Parity
⚠️ Indicates other packages or work are needed. See individual functions above.
Native | Luxon | date-fns | dayjs | Temporal | |
---|---|---|---|---|---|
Parse | |||||
String + Date Format | ✅ | ✅ | ✅ | ✅ | ✅ |
String + Time Format | ✅ | ✅ | ✅ | ⚠️ | ✅ |
String + Format + locale | ❌ | ⚠️ | ✅ | ⚠️ | ❌ |
Get + Set | |||||
Millisecond/Second/Minute/Hour | ✅ | ✅ | ✅ | ✅ | ✅ |
Date of Month | ✅ | ✅ | ✅ | ✅ | ✅ |
Day of Week | ✅ | ✅ | ✅ | ✅ | ✅ |
Day of Year | ✅ | ✅ | ✅ | ✅ | ✅ |
Week of Year | ✅ | ✅ | ✅ | ⚠️ | ✅ |
Days in Month | ✅ | ✅ | ✅ | ✅ | ✅ |
Weeks in Year | ❌ | ❌ | ✅ | ⚠️ | ✅ |
Maximum of the given dates | ✅ | ✅ | ✅ | ⚠️ | ✅ |
Minimum of the given dates | ✅ | ✅ | ✅ | ⚠️ | ✅ |
Manipulate | |||||
Add | ✅ | ✅ | ✅ | ✅ | ✅ |
Subtract | ✅ | ✅ | ✅ | ✅ | ✅ |
Start of Time | ❌ | ✅ | ✅ | ✅ | ✅ |
End of Time | ✅ | ✅ | ✅ | ✅ | ✅ |
Display | |||||
Format | ✅ | ✅ | ✅ | ✅ | ✅ |
Time from now | ✅ | ❌ | ✅ | ⚠️ | ✅ |
Time from X | ❌ | ❌ | ✅ | ⚠️ | ✅ |
Difference | ✅ | ✅ | ✅ | ✅ | ✅ |
Query | |||||
Is Before | ✅ | ✅ | ✅ | ✅ | ✅ |
Is Same | ✅ | ✅ | ✅ | ✅ | ✅ |
Is After | ✅ | ✅ | ✅ | ✅ | ✅ |
Is Between | ❌ | ✅ | ✅ | ⚠️ | ❌ |
Is Leap Year | ✅ | ✅ | ✅ | ⚠️ | ✅ |
Is a Date | ✅ | ✅ | ✅ | ✅ | ✅ |
Parse
String + Date Format
Return the date parsed from date string using the given format string.
// Moment.js
moment('12-25-1995', 'MM-DD-YYYY');
// => "1995-12-24T13:00:00.000Z"
// Native
const datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
const [, month, day, year] = datePattern.exec('12-25-1995');
new Date(`${month}, ${day} ${year}`);
// => "1995-12-24T13:00:00.000Z"
// date-fns
import parse from 'date-fns/parse';
parse('12-25-1995', 'MM-dd-yyyy', new Date());
// => "1995-12-24T13:00:00.000Z"
// dayjs
dayjs('12-25-1995');
// => "1995-12-24T13:00:00.000Z"
// luxon
DateTime.fromFormat('12-25-1995', 'MM-dd-yyyy').toJSDate();
// => "1995-12-24T13:00:00.000Z"
// Temporal
const datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
const [, month, day, year] = datePattern.exec('12-25-1995');
new Temporal.ZonedDateTime.from({year, month, day, timeZone: Temporal.Now.timeZone()});
// => "1995-12-24T13:00:00.000Z"
String + Time Format
Return the date parsed from time string using the given format string.
// Moment.js
moment('2010-10-20 4:30', 'YYYY-MM-DD HH:mm');
// => "2010-10-19T17:30:00.000Z"
// Native
const datePattern = /^(\d{4})-(\d{2})-(\d{2})\s(\d{1,2}):(\d{2})$/;
const [, year, month, day, rawHour, min] = datePattern.exec('2010-10-20 4:30');
new Date(`${year}-${month}-${day}T${('0' + rawHour).slice(-2)}:${min}:00`);
// => "2010-10-19T17:30:00.000Z"
// date-fns
import parse from 'date-fns/parse';
parse('2010-10-20 4:30', 'yyyy-MM-dd H:mm', new Date());
// => "2010-10-19T17:30:00.000Z"
// dayjs ⚠️ requires customParseFormat plugin
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);
dayjs('2010-10-20 4:30', 'YYYY-MM-DD HH:mm');
// => "2010-10-19T17:30:00.000Z"
// luxon
DateTime.fromFormat('2010-10-20 4:30', 'yyyy-MM-dd H:mm').toJSDate();
// => "2010-10-19T17:30:00.000Z"
// Temporal
const datePattern = /^(\d{4})-(\d{2})-(\d{2})\s(\d{1,2}):(\d{2})$/;
const [, year, month, day, hour, minute] = datePattern.exec('2010-10-20 4:30');
new Temporal.ZonedDateTime.from({year, month, day, hour, minute, timeZone: Temporal.Now.timeZone()});
// => "2010-10-19T17:30:00.000Z"
String + Format + locale
Return the date parsed from string using the given format string and locale.
// Moment.js
moment('2012 mars', 'YYYY MMM', 'fr');
// => "2012-02-29T13:00:00.000Z"
// date-fns
import parse from 'date-fns/parse';
import fr from 'date-fns/locale/fr';
parse('2012 mars', 'yyyy MMMM', new Date(), { locale: fr });
// => "2012-02-29T13:00:00.000Z"
// dayjs ⚠️ requires customParseFormat plugin
import customParseFormat from 'dayjs/plugin/customParseFormat';
import 'dayjs/locale/fr';
dayjs.extend(customParseFormat);
dayjs('2012 mars', 'YYYY MMM', 'fr');
// => "2012-02-29T13:00:00.000Z"
// Luxon ❌ does not support Locale for node unless https://moment.github.io/luxon/docs/manual/install.html#node
DateTime.fromFormat('2012 mars', 'yyyy MMMM', { locale: 'fr' });
// => "2012-02-29T13:00:00.000Z"
Get + Set
Millisecond / Second / Minute / Hour
Get the Millisecond/Second/Minute/Hour
of the given date.
// Moment.js
moment().seconds();
// => 49
moment().hours();
// =>