Formatting Dates in Node with Moment.js

Working with dates in a Node app can be tricky as there are so many ways to format and display them.

The APIs available in native JavaScript are way too tedious to use directly, so your best option is to use a date/time library. The best known and most flexible option is Moment.js.

What you'll learn#

  • Why you should use a date/time library in Node.js

  • How to install Moment

  • How to parse standard and non-standard date strings and timestamps with Moment

  • How to display a date with Moment in your desired format

  • Alternatives to Moment if it doesn't quite fit your needs

PrerequisiteS#

For this article, I'll presume you understand the basics of JavaScript and Node.js.

For more on JavaScript, check out these interesting articles to enhance your grasp on the subject.

To install Moment you should have Node and NPM installed on your machine. Any current version will do, but if you're installing from scratch, I'd recommend using the Node v12 LTS which includes NPM 6.

Why use Moment?#

Other than for simple use cases and one-offs, the JavaScript Date API will be too low-level and will require you to write many lines of code for what seems like a simple operation.

Moment is an incredibly flexible JavaScript library that wraps the Date API giving you very convenient helper methods allowing you to easily perform tasks like:

  • Parsing dates

  • Manipulating dates

  • Displaying dates

  • Converting between locales and timezones

Moment can be used in either the browser or on a Node.js server.

Installing Moment in Node.js#

Let's begin by going to the terminal and installing Moment:

With that done, we can now require the Moment library in a Node.js project:

The first thing we'll do to use Moment is to create a new instance by calling the moment method.

The moment instance#

So what is a Moment instance, and what exactly has been assigned to the variable m in the snippet above?

Think of the Moment instance as a wrapper object around a single, specific date. The wrapper provides a host of API methods that will allow you to manipulate or display the date.

For example, we can use the add method which, as you'd expect, allows you to add a time period to a date:

Note that Moment provides a fluent API, similar to jQuery. It's called "fluent" because the code will often read like a sentence. For example, read this line aloud and it should be immediately obvious what it does:

Another aspect of fluent API methods is that they return the same object allowing you to chain additional methods for succinct and easy to read code.

Note: one counter-intuitive aspect of Moment objects is that they are mutable. Calling any of the "manipulation" methods e.g. add, subtract, etc, will change the object they're applied to.

Parsing dates#

We said above that Moment wraps a single, specific date. So how do we specify the date we want to work with?

Current date#

Just like with the native JavaScript Date object, if we don't pass anything to the moment method when we first call it, the date associated with the instance will be the current date i.e. "now".

Fixed date#

What if we want to create a Moment instance based on some fixed date in the past or future? Then we can pass the date as a parameter to moment. There are several ways to do this depending on your requirements.

Formatted strings#

You may be aware of some of the standards for formatting date strings (with unfortunate names like "ISO 8601" and "RFC 2822"). For example, my birthday formatted as an ISO 8601 string would look like this: "1982-10-25T08:00:15+10:00";.

ISO 8601 is a standard designed to provide an unambiguous and well-defined method of representing dates and times. RFC 2822 is designed for similar purposes but is more specifically designed for use on the internet and in email.

Since these standards are designed for accurately communicating dates, you'll probably find that your database and other software will provide dates in one of these formats.

If your date is formatted as either ISO 8601 or RFC 2822, Moment is able to automatically parse it.

If your date string is not formatted using one of these standards, you'll need to tell Moment the format you're using. To do this, you supply a second argument to the momentmethod - a string of format tokens.

Format token Templates#

Most date string formats are specified using format token templates. It's easiest to explain these using an example. Say we created a date in the format "1982-10-25". The format token template representing this would be "YYYY-MM-DD". If we wanted the same date it in the format "10/25/82" the template would be "MM/DD/YY".

Hopefully, that example makes it clear that the format tokens are used for a unique date property e.g. "YYYY" corresponds to "1982", while "YY" is just "82".

Format tokens are quite flexible and even allow us to create non-numeric values in dates like "25th October, 1982" - the format token string for this one would be "Do MMMM, YYYY" (note that including punctuation and other non-token values in the template is perfectly okay).

For a complete list of date format tokens, see this section of the Moment docs.

Specifying date format#

So, if you want to use non-standard formatting for a date, supply the format token template as the second argument and Moment will use this to parse your date string.

For example, shorthand dates in Britain are normally formatted as "DD-MM-YYYY", while in America they're normally formatted as "MM-DD-YYYY". This means a date like the 10th of October, 2000 will be ambiguous (10-10-2000) and so Moment cannot parse it accurately without knowing the format you're using.

If we provide the format token template, however, Moment knows what you're looking for:

Timestamps#

A Unix timestamp is a way to track time as a running total of seconds starting from the "epoch" time: January 1st, 1970 at UTC. For example, the 10th of October, 2000 is 971139600 seconds after the epoch time, therefore that value is the Unix timestamp representing that date.

You'll often see timestamps used by operating systems as they're very easy to store and operate on.

If you pass a number to the moment method it will be parsed as a Unix timestamp:

Fun fact: Unix timestamps will reach the 32-bit limit on January 19, 2038, after which time they'll cease to work! Luckily, there's a 64-bit replacement being introduced.

Formatting dates#

Now we've learned how to parse dates with Moment. How can we display a date in a format we like?

The API method for displaying a date in Moment is format and it can be called on a moment instance:

As you can see in the console output, Moment will, by default, format a date using the ISO 8601 format. If we want to use a different format, we can simply provide a formatted token string to the method. For example, say we wanted to display the current date in the British shorthand "DD-MM-YYYY":

Here's another example showing a more reader-friendly date:

Alternatives to Moment#

While it's the most popular date library, Moment is certainly not the only option. You can always consider an alternative library if Moment doesn't quite fit your needs.

One complaint developers have about Moment is that the library is quite large (20kB+). As an alternative, you might try Day.js which is a 2kB minimalist replacement for Moment.js, using an almost identical API.

Another complaint is that the Moment object is mutable, which can lead to confusing code. One of the maintainers of Moment has released Luxon, a Moment-inspired library that provides an immutable and unambiguous API.

Conclusion#

So now you know how to format dates using Moment and Node. You understand how to work with the current date, as well as how to use standard and non-standard date strings. You also know how to display a date in whatever format you like by supplying a format token template.

Here's a snippet summarizing the main use case:

More resources#

Parsing and displaying dates just scratches the surface of Moment's features. You can also use it to manipulate dates, calculate durations, convert between timezones, and more.

If you'd like to learn more about these features I'd recommend you start with the Moment docs: