Formatting and modifying JavaScript dates with date-fns
Tags: javascript, datefns, momentjs
Published: 2019-01-20 06:03:22

Date manipulation in JavaScript may seem like a daunting thing to accomplish. The native [`Date()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object is not very novice friendly and it requires a ton of work for simple tasks like formatting.

There are currently two big players when it comes to JavaScript libraries for date management. [MomentJS](https://momentjs.com/) and [Date-FNS](https://date-fns.org/).

# Why date-fns?

Both libraries get the job done, they allow you to grab a `Date` object and format, add time, subtract time, etc. However there is one clear core difference between the two that may be a selling point in your future projects.

Date-fns is **modular** meaning you only import what you need, which prevents a lot of bloating in your final packed files. This may not seem like a huge deal, but importing the whole MomentJS library to just have a simple formatting function may not be what you are looking for.

It is also **immutable**, which means for every function you will always get back a _new_ `Date` object. This makes debugging a walk in the park.

The **documentation** is super clear and simple, and has clear use examples for every function. You can check it out here: [date-fns documentation](https://date-fns.org/docs/Getting-Started).

# Getting started

Let's dive right in and import date-fns to a starter project.

```shell
# If you use NPM
npm install date-fns

# If you use YARN
yarn add date-fns
```

**Note:** If you're following this article and don't want to use package managers, you can import the whole library with `<script src="http://cdn.date-fns.org/VERSION/date_fns.min.js"></script>` but you'll miss out on importing just the modules you want/need. 

Also, keep in mind that when using **date-fns** via `<script>` or from an online editor like `CodeSandbox` instead of calling a function directly like we will in this article, you will have to call it through the `dateFns` object. 
Ex: `dateFns.addDays()`

Once you've added the library to your project, you can head over to your JavaScript file and start importing functions!

# Formatting

Formatting is the go-to necessity when working with JavaScript dates, so we'll tackle it first.

Import the `format` function on your file by calling:

```js
import { format } from 'date-fns';
```

Or in case you're working on a NodeJS project:
```js
const { format } = require('date-fns');
```

**Tip:** If you don't already know, the bit between the import braces `{ format }` allows us to import **only** the `format` function to your file, so you only actually bring in the functions that this file will use!

Let's create a new date to work with: `const newYears = new Date(2019, 1, 1);`, this will give us a constant `newYears` with a native JS date for Jan 1st, 2019.

Now let's go ahead and format this date in a MM/DD/YYYY format.

```javascript
const newYears = new Date('2019/01/01');
const formattedDate = format(newYears, 'MM/DD/YYYY');
console.log(formattedDate);
```

If you run this and check out your console output, you'll see that you are getting back your formatted string. `01/01/2019`

_Wait, that's it?_ Yup! Date-fns makes formatting super simple!

If you want to check out the different formatting options, check out the [official documentation for the format function](https://date-fns.org/v1.30.1/docs/format) for a full reference. 

# Adding a locale

Ok, so formatting is a very straight forward task. But **date-fns** also supports a simple way to localize formatted date output.

Let's grab our previous example and change it to a French locale, with a full month-name format. We just need to `require` the locale, and pass it to the format option. It will take an optional 3rd argument for an options object.

```javascript
const newYears = new Date('2019/01/01');
const frenchLocale = require('date-fns/locale/fr');

const formattedDate = format(newYears, 'MMMM DD, YYYY', { locale: frenchLocale });
console.log(formattedDate);
```

Très bien! The output now is `janvier 01, 2019`

# Adding and subtracting

Now that we know how to format dates, let's move on to actually manipulating our initial date.

In `date-fns` we have a function for each type of operation: 

* [addDays](https://date-fns.org/v1.30.1/docs/addDays)
* [addWeeks](https://date-fns.org/v1.30.1/docs/addWeeks)
* [addMonths](https://date-fns.org/v1.30.1/docs/addMonths)
* [subDays](https://date-fns.org/v1.30.1/docs/subDays)
* [subWeeks](https://date-fns.org/v1.30.1/docs/subWeeks)
* [subMonths](https://date-fns.org/v1.30.1/docs/subMonths)

Starting to see a pattern here? There is quite a bit of adding/subtracting functions to work with. Make sure you head over to the docs to check out all the functions you can work with!

Let's grab our previous example and add a year to it, so that we're working with 2020's year start.

First, start by adding the `addYears` function to our import statement.

```javascript
import { format, addYears } from 'date-fns';
```

Now that we have the function accessible, we can add a year to our base date, and then format the output.

```js
let newYears = new Date('2019/01/01');
newYears = addYears(newYears, 1);

const formattedDate = format(newYears, 'MMMM DD, YYYY');
console.log(formattedDate);
```

The output now should be `January 01, 2020`

# Calculating the number of days between two dates

Up for one more? How about for this one we calculate the number of days between the 1st day of the year and Christmas?

Let's first add the `date-fns` function `differenceInDays`:

```js
import { format, addYears, differenceInDays } from 'date-fns';
```

We only now have to create both dates, and pass them to the function:

```js
const firstDay = new Date('2019/01/01');
const christmas = new Date('2019/12/24');

const daysBetween = differenceInDays(christmas, firstDay);
console.log(daysBetween); // Outputs => 357
```

# Conclusion

Date-fns may be daunting to look at, but in practice is a super simple and lightweight way to handle all your date calculations!

**Bonus pro tip:** Need to test one of the date-fns functions on the spot? Fire up your developer tools while browsing the documentation, and you can use all the functions on the spot through the `dateFns` object. Thank you [Malinda M.](https://twitter.com/BeerAndBlank) for pointing this out!