iJS CONFERENCE Blog

Why you should use date-fns for manipulating dates with JavaScript

Mar 27, 2019

Issues related to working with dates are as old of a problem as it gets with JavaScript. In theory it is possible to perform date calculations with JavaScript’s date object, if it weren’t for the many weaknesses of the API. Fortunately, there are helpful libraries that can save us a lot of work. One of them is date-fns.

One problem, for example, is the handling of different time zones with the date object, since JavaScript uses the current system time zone as a basis. This can lead to difficulties, especially when it comes to applications that span multiple time zones. The representation of the month is another peculiarity of the date object in JavaScript. January, for instance, is specified with the value 0. However, when it comes to dates of days and years, JavaScript follows the expected standard again, thus the 5th of the month is represented by the number 5.

When you are implementing an application that works with date values, you will often stumble upon the problem that you have to create, modify, and output them. With the on-board JavaScript tools, the creating and outputting is easily doable. However if a date is modified, for example if you want to subtract two days from a date, this is no longer possible. Of course, you can get the timestamp of the date and then subtract the respective number of milliseconds in order to reach the target date. This solution is not easy to read and maintain, or particularly elegant. Due to this issue, and many more, numerous libraries have been created in the past to make it easier for you to handle date values in JavaScript. One of the most widespread solutions on the market is Moment.js. The top dog got a serious competitor some time ago though: The project date-fns.

How does date-fns differ from Moment.js?

The first and one of the most important differences is already in the name of the project, since fns stands for functions. date-fns is a collection of functions that allow you to work with date values.
In contrast to that, Moment.js has an object-orientated approach. Here you create a Moment-instance and work with the methods of this object. This affects the package size of course.
Moment.js contains the entire interface by default. You can indeed optimize the package, but this requires additional steps. In date-fns you only load the functions that you really need.
This doesn’t matter too much in a backend application with Node.js though, since the package size is a minor concern. You can use date-fns just like Moment.js, in the frontend browser. It’s here that the package size is decisive.

The developers of date-fns have not only made sure that the project is divided into many small and largely independent functions, but also that the functions are pure functions. For example, you pass a date object and the number of hours to add to the addHours function. As a result you get a new date object where the specified number of hours is later than when you entered it. So there are no side effects, such as the direct modification of the input.

How to install date-fns?

Like most other JavaScript libraries, date-fns is available as an npm package and can be installed as such via npm. Use the command npm install date-fns in your project to do so. The package will automatically be added to your package.json file as a dependency. Likewise, you can use yarn with the yarn add date-fns command.

How to use it?

You can use the date-fns package with both the CommonJS module system and also with ES modules. In the following example, you use the format function to output the current date. Listing 1 shows you how to work with the CommonJS module system.

 

const { format } = require('date-fns');

const date = new Date();

console.log(`Heute ist der: ${format(date, 'DD.MM.YYYY')}`);

Newer versions of Node.js also support the keywords import and export in order to import and export modules respectively. At this point you can either import the entire date-fns package and access the required functions, or you can take advantage of the fact that each function is available in a separate file, so you can import the format function individually. You can see how this works in Listing 2.

import { format } from 'date-fns/format';
const date = new Date();
console.log(`Heute ist der: ${format(date, 'DD.MM.YYYY')}`);

 

Become a part of our International JavaScript community now!
LEARN MORE ABOUT iJS Munich 2019:

 
Formatting date values

With format you have already learned the most important function for formatting date values.
You can use the format string to specify which part of the date you want to format and how.
A comprehensive reference of the individual tokens that you can use in the format string can be found at https://date-fns.org/docs/format.

In addition to this function, you have access to other auxiliary functions such as the distanceInWords function that outputs the difference between two date values in a readable form.

Date arithmetic

An already mentioned, vulnerability of object dates in JavaScript is the lack of support for a date arithmetic. It is therefore not possible to perform addition or subtraction without further ado.
date-fns provides a number of auxiliary functions for this. These functions generally have a uniform naming scheme: First you specify the operation, followed by the unit you want to work with.
This results in function names such as addMinutes or subYears. All functions of this category accept a date object as the first argument and a number as the second indicates how many units you want to add or subtract. For example, to add three quarters of an hour to the current date, you can use the code from Listing 3.


const { addMinutes, addHours, format } = require('date-fns');

const date = addMinutes(addHours(new Date(), 1), 45);

console.log(format(date, 'DD.MM.YYYY HH:mm'));

Comparisons

The comparison functions of date-fns are also very helpful, with their help you can determine whether a date lies before or after another, or whether a certain date lies in the future or in the past. Listing 4 uses the isAfter and isFuture functions as examples to illustrate their use.

const { isAfter, isFuture, addHours } = require('date-fns');

const date1 = new Date();
const date2 = addHours(new Date(), 5);
console.log(`Date1 is ${isAfter(date1, date2) ? 'after' : 'before'} Date2`);
console.log(`Date2 is ${isFuture(date2) ? 'not' : ''} in the past`);

Further operations

The date-fns package offers you not only simple operations such as addition, but also more complex operations such as the areRangesOverlapping function, which you can use to determine whether two time spans overlap.

With the min and max function you can find the earliest or latest date of a series of date values.

With the help of the compareAsc and compareDsc functions you can also sort arrays with date values. This function is passed to the sort method of an array as a comparison function. Listing 5 is an example of this.


const { compareAsc } = require('date-fns');



const sortedDates = [

new Date(2001, 1, 1),

new Date(2003, 3, 3),

new Date(2002, 2, 2),

].sort(compareAsc);



console.log(sortedDates);

Conclusion

A lot of what packages like Moment.js or date-fns offer, you can also achieve with native JavaScript. However, in these cases the source code readability suffers greatly. This is one of the most important arguments in favour of using these libraries, in addition to correcting the peculiarities of the JavaScript date object.

The possibilities of the date-fns shown here represent only a small part of the library and shall only give you a taste of this library’s functional scope. With numerous extensions and very good support for internationalization in applications, you should at least shortlist date-fns the next time for when you decide upon a date library for one of your applications.

Sign up for the iJS newsletter and stay tuned to the latest JavaScript news!

 

BEHIND THE TRACKS OF iJS

JavaScript Practices & Tools

DevOps, Testing, Performance, Toolchain & SEO

Angular

Best-Practises with Angular

General Web Development

Broader web development topics

Node.js

All about Node.js

React

From Basic concepts to unidirectional data flows