Working with JavaScript Dates Using Moment.js

Jul 18 2014 by Bradley Holbrook | No Comments

Date manipulation is one of those development hurdles that we all must jump at one point in our career, and great tools go a long way in taming the beast.

The Moment.js library is that tool for JavaScript developers.

Since discovering Moment.js, an open source project, I’ve used it religiously to simplify validation, parsing and manipulation of dates on the client-side.

In this tutorial, I’ll help you get up and running with this ultra-useful JavaScript date library.

What is Moment.js?

Moment.js is a free and open source JavaScript library that removes the need to use the native JavaScript Date object directly. The library is a wrapper for the Date object (in the same way that jQuery is a wrapper for JavaScript) making the object a whole lot easier to work with.

The problem with JavaScript’s Date object isn’t the functionality it brings; it’s just extremely cumbersome to use as a developer. If you want to do complex parsing, validation and displaying of dates, you’ll end up writing a lot of code.

Moment.js also extends native JavaScript date capabilities with a variety of features, such as relative time, calendar time, durations and multi-language support. It has a seemingly endless list of plugins that allow for additional features like time-zone support, recurrence and Twitter integration.

Tutorial Information

In this tutorial, we’re going to take a look at Moment.js. The following are the things we’ll tackle.

  • Referencing Moment.js and displaying basic date outputs
  • Displaying formatted dates
  • Parsing dates
  • Detecting invalid dates
  • Correcting invalid dates
  • Adding and subtracting dates

There are demo pages for almost all the sections of this tutorial that demonstrate the code being discussed.

Alternatively, you can download all the demo files associated with this tutorial as a ZIP archive.

Download All Demo Files

Let’s dive in.

Referencing Moment.js and Displaying Basic Outputs

To get started, you’ll need to download Moment.js and reference it in your HTML document. You can also find the library at cdnjs.com (a public CDN for open source projects). Just search for the library using the term "moment.js".

The first thing we’re going to do in this tutorial is to reference the Moment.js library.

Then, to make sure it’s working properly, we’re going to instantiate a moment object and a JavaScript Date object, and then output their values.

The following shows you how to reference the Moment.js library in your HTML documents, as well as how to instantiate and display the values of the moment object and the JavaScript Date object.

<!DOCTYPE html>
<html>
<head>
  <!-- reference Moment.js library -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js" type="text/javascript"></script>
</head>
<body>

<h2>Moment Date</h2>
<!-- container for Moment.js output -->
<div id="displayMoment"></div>

<h2>JavaScript Date</h2>
<!-- container for JavaScript Date output -->
<div id="displayJsDate"></div>

<script type="text/javascript">
(function()
{
  // instantiate a moment object
  var NowMoment = moment();
  
  // instantiate a JavaScript Date object
  var NowDate = new Date();
  
  // display value of moment object in #displayMoment div
  var eDisplayMoment = document.getElementById('displayMoment');
  eDisplayMoment.innerHTML = NowMoment;
  
  // display value of Date object in #displayJsDate div
  var eDisplayDate = document.getElementById('displayJsDate');
  eDisplayDate.innerHTML = NowDate;
})();
</script>

</body>
</html>

View Demo 1

At this point, the code-lengths of both the moment and native Date object look on par.

Displaying Formatted Dates

Things between moment and JavaScript Date quickly change, however, when we want to output even a simple, human-readable date display with the format of ‘Y-m-d’ (e.g. ’2014-7-1′).

Using JavaScript Date, this would be our code.

// use JavaScript Date to display current date in a div (#displayJsDate)
var NowDate = new Date();
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var sDay = NowDate.getDate();
var sMonth = NowDate.getMonth() + 1;
var sYear = NowDate.getFullYear();
var eDisplayDate = document.getElementById('displayJsDate');
eDisplayDate.innerHTML = sYear+'-'+sMonth+'-'+sDay;

Moment.js makes our code terser.

// use Moment.js to display current date in a div (#displayMoment)
var NowMoment = moment();
var eDisplayMoment = document.getElementById('displayMoment');
eDisplayMoment.innerHTML = NowMoment.format('YYYY-M-D');

View Demo 2

You’ll notice we had to add a lot of set-up code for our specific date format output in the native solution, and only a simple method called .format() in the Moment solution.

The string argument that we passed into .format(), which is 'YYYY-M-D', is the format that we’re asking the Moment.js library to return the date in. The Moment.js website has many format options conveniently listed in a table here:

Now that we’re familiar with the process of displaying and formatting the current date, let’s move on.

Parsing Dates

The Moment initializer will take a parameter and set the Date object to that date.

<h2>Output Date</h2>
<div id="output"></div>

<script type="text/javascript">
(function()
{
  var Date = moment('July 1, 2014');
  var eDisplayMoment = document.getElementById('output');
  // display output in the preferred format
  eDisplayMoment.innerHTML = Date.format('YYYY-M-D');
})();
</script>

One detail to note is there’s no standard that browsers adhere to when parsing dates. Fortunately, the Moment.js library provides additional parameters that allow us to specify the exact pattern we’re passing in to help us avoid cross-browser inconsistencies.

For consistency across all browsers and platforms, the above code should be parsed like the fowlloing.

<h2>Input Date</h2>
<div id="input">July 1, 2014</div>

<h2>Output Date</h2>
<div id="output"></div>

<script type="text/javascript">
(function()
{
  // get the input date from #input div element
  var input = document.getElementById('input').innerHTML;
  
  // use moment() with input value and a string format pattern as arguments
  var Date = moment(input, 'MMMM D, YYYY');
  
  // display the parsed date in a div (#output)
  var eDisplayMoment = document.getElementById('output');
  eDisplayMoment.innerHTML = Date.format('YYYY-M-D');
})();
</script>

View Demo 3

The Moment.js website has another table displaying the available parameters that we can use for parsing:

As the value we’re parsing is rarely entered by hand, it’s important to know that we’re actually parsing a date value.

Consider the input '2014-14-14' — this is an impossible date. In this case the moment() function will actually return the string 'Invalid Date' if you try to parse it.

However, there are additional tools available to us for detecting and correcting an invalid date values.

Detecting Invalid Dates

To detect an invalid date, Moment.js provides us with the isValid() method. It returns a simple boolean value (true or false), enabling us to determine the next course of action in our code logic in case the date value is not a valid one.

The other detection method available is invalidAt(). This method is more specific, it will tell us where our date value is invalid. It will return an integer between 0 and 6, the meanings of which can be found in the following table.

Integer Error location
0 Years
1 Months
2 Days
3 Hours
4 Minutes
5 Seconds
6 Milliseconds

So, in the example of '2014-14-14', the invalidAt() function would return 1 because 14 is an invalid month (only 1-12 are valid month values).

Correcting Invalid Dates

When would you ever be able to correct an invalid date? If you haven’t worked with dates at length before, this one might stump you. However, there are more variables at play than just the date itself: We must also consider how we’re getting the date and who is providing it.

Often, we ask people to enter dates and, despite our best efforts and flashy tooltips asking them to input in a specific date format like "d/m/y", they ignore our instructions and provide "m/d/y" anyways.

We can go back to the date-parsing call we made earlier and add a second parsing parameter (you can have more than two options) by passing in a string array of various possible date formats as a fallback.

Let’s use the date January 1, 2014 as our input example. We’ll input 14/1/2014 and 1/14/2014 expecting an input of D/M/YYYY.

<h2>Input Dates</h2>
<div id="input1">14/1/2014</div>
<div id="input2">1/14/2014</div>

<h2>Output Dates (1 format)</h2>
<div id="output1"></div>
<div id="output2"></div>

<h2>Output (multiple formats)</h2>
<div id="output3"></div>
<div id="output4"></div>

<script type="text/javascript">
(function()
{
  var correct = document.getElementById('input1').innerHTML;
  var incorrect = document.getElementById('input2').innerHTML;
  
  var Date1 = moment(correct, 'D/M/YYYY');
  document.getElementById('output1').innerHTML = Date1.format('MMMM D, YYYY');
  
  var Date2 = moment(incorrect, 'D/M/YYYY');
  // will display 'Invalid Date' in #output2 because input format is incorrect
  document.getElementById('output2').innerHTML = Date2.format('MMMM D, YYYY');

  var Date3 = moment(correct, ['D/M/YYYY','M/D/YYYY']);
  document.getElementById('output3').innerHTML = Date3.format('MMMM D, YYYY');

  // will try to parse using two potential date formats
  var Date4 = moment(incorrect, ['D/M/YYYY','M/D/YYYY']);
  // will display correct date format
  document.getElementById('output4').innerHTML = Date4.format('MMMM D, YYYY');
})();
</script>

View Demo 4

You’ll notice that with just one string argument, if the input doesn’t match, you will output 'Invalid Date'.

However, if you provide an array of string formats as the argument, the first parsing option that works will be used. This is great for removing or anticipating possible user errors.

Adding and Subtracting Dates

One of my favorite features in the Moment.js library is it conveniently has date-manipulation methods, such as .add() and .subtract().

For example:

// current date
var Date = moment();

// add 7 days to current date
document.getElementById('currDatePlus7d').innerHTML = Date.add('days', 7);

// subtract 8 hours from current date
document.getElementById('currDateSub8h').innerHTML = Date.subtract('hours', 8);

// add 5 years and 3 months to current date
document.getElementById('currDatePlus8h').innerHTML = Date.add({years: 5, months: 3});

View Demo 5

The Moment.js library will handle edge-cases elegantly. For example, using the native JavaScript Date object, adding one month to August 31 will result in October 1. This same operation performed by Moment.js will correctly produce September 30.

Conclusion

Moment.js is an excellent tool to have if you regularly end up working with client-side date parsing, formatting and validation. It has plenty to offer in terms of speeding up JavaScript development in this area. To see the project’s source code, head over to its GitHub repository. To learn more about its features, check out the official docs.

Related Content

About the Author

Bradley Holbrook is a senior software developer for Click4Time Software Inc. He has been designing and developing web applications for over 15 years. Connect with Bradley via email.

Leave a Comment

Subscribe to the comments on this article.