Skip to main content

Managing Dates and Times Using Moment.js

By Jay Raj, James Hibbard

JavaScript

Share:

JavaScript: Novice to Ninja, 2nd Edition

Build your JavaScript skills on a rock-solid foundation.

Working with dates and times in JavaScript has always been a bit cumbersome. Native date methods are verbose and the API is often inconsistent. That’s why if you ask a date-related question on StackOverflow, you’ll often hear the reply “Use Moment.js”.

What Is Moment.js?

Moment.js is a Swiss Army knife for working with dates in JavaScript. It allows you to parse, validate, manipulate, and display dates and times using a clean and concise API.

In this article I’ll show you how to get up and running with Moment.js, as well as demonstrate several of its common use cases.

Getting Started with Moment.js

Moment.js is freely available for download from the project’s home page. Moment.js can be run from the browser as well as from within a Node application. In order to use it with Node, install the module using the following command.

npm install moment

Then, simply require() and use it in your application as shown below.

const moment = require('moment');
const today = moment();
console.log(today.format());

// 2020-01-09T15:45:51+01:00

In order to run Moment.js from the browser, include it using a <script> tag, as shown below. Moment.js creates a global moment object which can be used to access all the date and time parsing and manipulation functionality.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Moment.js</title>
  </head>
  <body>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
    <script>
      // You have a 'moment' global here
      const today = moment();
      console.log(today.format());
    </script>
  </body>
</html>

Date Formatting

In the past, I recall converting date strings into Date objects, grabbing individual pieces of data, and then performing string concatenations. Moment.js has simplified the process of date conversion to any particular format. Date format conversion with Moment is simple, as shown in the following example.

moment().format('YYYY-MM-DD');

Calling moment() gives us the current date and time, while format() converts it to the specified format. This example formats a date as a four-digit year, followed by a hyphen, followed by a two-digit month, another hyphen, and a two-digit day.

See the Pen
Formatting the Date with Moment.js
by SitePoint (@SitePoint)
on CodePen.

Tip: Try experiment with some of the other date formats listed in the project’s documentation.

Date Validation

Another annoying task that Moment.js has greatly simplified is date validation. In order to perform validation, simply pass a date string to the moment object, along with the desired date format, and call the isValid() method. This will return true if the date is valid, and false otherwise.

console.log(moment("2020-01-01", "YYYY-MM-DD").isValid()); // true
console.log(moment("not-a-date", "YYYY-MM-DD").isValid()); // false

Be aware, however, that Moment gives you the possibility to work with partial dates, which might lead to unexpected results.

console.log(
  moment("2019 was a great year because I got married", "YYYY-MM-DD").isValid()
);
// Returns true because 2019 matches YYYY

To avoid this, you can put Moment into strict parsing mode by passing it true as a third argument.

console.log(
  moment("2019 was a great year because I got married", "YYYY-MM-DD", true).isValid()
);
// false

Here’s an example to showcase this functionality.

See the Pen
Checking Date Validity with Moment.js
by SitePoint (@SitePoint)
on CodePen.

There are a number of other helpful flags in the object returned by moment():

  • overflow – This is set when an overflow occurs. An example would be the 13th month or 32nd day.
  • invalidMonth – Set when the month is invalid, like Jannnuaarry.
  • empty – Set when the entered date contains nothing parsable.
  • nullInput – Set when the entered date is null.

You can read more about these and other available flags on the project’s homepage.

Manipulating Dates

Build better and faster

Get up and running with the powerful and modern Vue.js

Read the book now

There are a number of options for manipulating the moment object. For example, you can add or subtract days, months, years, etc. This is achieved via the add() and subtract() methods. The following example shows how seven days, months, or weeks are added to the current date.

moment().add(7, 'days');    // adds 7 days to current date
moment().add(7, 'months');  // adds 7 months to current date
moment().add(7, 'years');   // adds 7 years to current date

Similarly, the subtract() method is shown below.

moment().subtract(7, 'days');   // subtracts 7 days to current date
moment().subtract(7, 'months'); // subtracts 7 months to current date
moment().subtract(7, 'years');  // subtracts 7 years to current date

Note that each of the above examples will return the moment object. If you want a human-readable date, you’ll need to format it accordingly.

const today = moment();
const nextWeek = today.add(7, 'days');
console.log(nextWeek.format('dddd Do MMMM, YYYY'));

// Thursday 16th January, 2020

Time From Now

Another common task is determining how much time exists between two dates. For calculating time from the current date, Moment.js uses a method named fromNow(). Here’s how to check how much time has elapsed since the beginning of the decade:

moment('2020.01.01', 'YYYY.MM.DD').fromNow();
// 9 days ago

If we pass in true as an argument, we can get the value without the suffix.

moment('2020.01.01', 'YYYY.MM.DD').fromNow(true);
// 9 days

Time From Another Date

The fromNow() method is used to compare time to the current date. This is just a special case of from(), which compares two arbitrary dates. An example that utilizes from() is shown below.

const dateA = moment('01-01-1900', 'DD-MM-YYYY');
const dateB = moment('01-01-2000', 'DD-MM-YYYY');

console.log(dateA.from(dateB));

You can have a play with this method in the following demo.

See the Pen
Time From Another Date with Moment.js
by SitePoint (@SitePoint)
on CodePen.

Calculating the Difference Between Dates

Moment.js offers a way to calculate the difference between two dates. The difference is calculated in milliseconds by default, but can also be returned in days, months, years, etc. To compute the difference, call the diff() method. This method takes a date as its first argument. The unit of time can be specified using the optional second argument. If this is not included, then milliseconds are used. The following example and demo illustrate how diff() is used.

const dateB = moment('2014-11-11');
const dateC = moment('2014-10-11');

console.log('Difference is ', dateB.diff(dateC), 'milliseconds');
console.log('Difference is ', dateB.diff(dateC, 'days'), 'days');
console.log('Difference is ', dateB.diff(dateC, 'months'), 'months');

See the Pen
Calculating the Difference Between Dates with Moment.js
by SitePoint (@SitePoint)
on CodePen.

Date Queries

Moment.js also provides various date comparison methods. These methods include isBefore(), isAfter(), and isSame() which, as the names imply, return a Boolean indicating if one date is before, after, or equal to another date. An example that uses isAfter() is shown below.

console.log(moment('2020-01-01').isAfter('2019-01-01')); // true
console.log(moment('2020-01-01').isAfter('2020-01-08')); // false

There is also an isLeapYear() method that checks for leap years.

console.log(moment([2020]).isLeapYear()); // true
console.log(moment([2019]).isLeapYear()); // false

International Language Support

Moment.js offers great i18n support. It allows you to assign a global language or set the language for a particular moment object. By default, it supports the English language. If you want to support any other language, then assign the key values of that particular language to moment.locale. The following abridged example, taken from the Moment.js docs, shows how support can be added for French.

const moment = require('moment');

moment.locale('fr', {
  months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
  weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
  relativeTime : {
      future : 'dans %s',
      past : 'il y a %s',
      s : 'quelques secondes',
      m : 'une minute',
      mm : '%d minutes',
      h : 'une heure',
      hh : '%d heures',
      d : 'un jour',
      dd : '%d jours',
      M : 'un mois',
      MM : '%d mois',
      y : 'un an',
      yy : '%d ans'
  }
});

moment.locale('fr');

console.log(moment(1316116057189).fromNow());
// il y a une heure

console.log(moment().format('dddd Do MMMM, YYYY'));
// jeudi 9e janvier, 2020

See the Pen
Internationalization with Moment.js
by SitePoint (@SitePoint)
on CodePen.

Why Moment Might Not Be a Good Fit

Although Moment.js is an excellent time and date library, it is also something of a behemoth. For example, if you use it with webpack, just an innocent require('moment'); is enough ensure that all of the locales come along for the ride. This significantly increases your bundle size and you need to resort to plugins to get it back down.

It also comes with a great many features, but in contrast to libraries like Lodash, it doesn’t allow you to cherry-pick the ones you need. Rather, you always have to load the entire library.

Another common complaint is that the moment object is mutable. This can leads to confusion among developers. Consider:

const moment = require('moment');
const today = moment();
const nextWeek = today.add(7, 'days');
console.log(today.fromNow());

What would you expect to be logged to the console? Unfortunately, the answer is “in 7 days” (and not “a few seconds ago”), because the code today.add(7, 'days') mutated the moment object, setting it to seven days in the future.

This can be avoided by cloning the moment object before preforming any date math, but by the time you remember to do that, the chances are you’ve already spent quite some time debugging.

const moment = require('moment');
const today = moment();
const nextWeek = today.clone().add(7, 'days');
console.log(today.fromNow());
// a few seconds ago

A Light-weight Alternative

For those of you looking for a lighter alternative, consider date-fns. Date-fns is immutable, always returning a new date instead of changing the one you pass in. It has a simple API, is the perfect companion for Webpack and with its function-per-file style you can pick just what you need.

If you’d like to find out more, read: Introduction to date-fns – a Lightweight JavaScript Date Library

Conclusion

Moment.js is really an awesome library that simplifies date and time-related manipulations and validations. In this article, we focused on some of the features of Moment.js which help in parsing, validating, and manipulating dates and times in the browser and Node.js applications. A number of useful plugins are also available for Moment.js. Plugins like ISO Calendar, Jalaali Calendar, and many more can be found on the official plugin page. For more on Moment.js, the reader is directed to the library’s documentation.

Jay is a Software Engineer and Writer. He blogs occasionally at Code Handbook and Tech Illumination.

Currently I work for SitePoint as editor of their JavaScript hubs and technical editor for various books (e.g. JavaScript: Novice to Ninja and Jump Start Vue.js). I also work as a network admin and freelance web dev, where I spend a fair bit of my time working on Rails apps.

New books out now!

Learn valuable skills with a practical introduction to Python programming!


Give yourself more options and write higher quality CSS with CSS Optimization Basics.