Using date-fns for Easy Date Manipulation
Date manipulation is a common task in JavaScript, and the native Date
object provides some basic functionality. However, handling dates can be complex and error-prone, and Date
lacks the functionality needed to perform those common tasks. To make working with dates easier and more reliable, developers must rely on third-party libraries. There are many available in the JavaScript ecosystem, but date-fns stands out as the de facto standard. It's a lightweight utility library for parsing, formatting, and manipulating dates.
In this tutorial, we will explore the basics of using date-fns and cover the most commonly used functions for working with dates. By the end, you'll have a solid understanding of how to incorporate date-fns into your JavaScript projects to effectively handle dates.
Installing date-fns
date-fns is a Node package. So, if you are using a tool stack such as NPM, Babel, or Webpack, then you can install date-fns using the following npm command:
1 |
npm install date-fns --save |
If any of that was Greek to you, then don't worry; you can use date-fns in the browser, too! Simply add the following <script/>
element to your HTML:
1 |
<script type="module"> |
2 |
import * as dateFns from 'https://cdn.jsdelivr.net/npm/date-fns/+esm'; |
3 |
</script>
|
This is a JavaScript module that imports the latest version of the date-fns library from the jsdelivr network. With this import, all date-fns functions and utilities are accessible through the dateFns
object. Note that to successfully run all code in this tutorial, the code must be contained within the same module that imported date-fns.
Formatting Dates
One of the primary tasks when working with dates is formatting them into human-readable strings. JavaScript's Date
object has basic support for formatting dates, but it lacks support for custom formats. date-fns provides the format function for this purpose.
1 |
const today = new Date(); |
2 |
const formattedDate1 = dateFns.format(today, 'dd MMMM yyyy'); |
3 |
console.log(formattedDate1); // Output: "29 July 2023" |
4 |
|
5 |
const formattedDate2 = dateFns.format(today, 'yyyy-MM-dd'); |
6 |
console.log(formattedDate2); // Output: 2023-07-29 |
In this example, we create a new Date
object representing the current date. We then use the format()
function to format the date according to the provided format string. The format string uses placeholders such as dd
for a two-digit day, MMMM
for the full month name, and yyyy
for the full year.
The second call to format()
uses the yyyy-MM-dd
format. The MM
placeholder refers to the two-digit month.
The format()
function also makes it easy to format the time. Use the h
or hh
placeholders to output the one- or two-digit hour, mm
for two-digit minutes, and a
for the AM/PM indicator. For example:
1 |
const formattedDateAndTime = dateFns.format(today, 'yyyy-MM-dd h:mm a'); |
2 |
console.log(formattedDateAndTime); // Output: 2023-07-29 12:50 PM |
There are many placeholders you can use to format dates and times. Some are listed in the following table, but be sure to visit the documentation for the complete list.
Unit | Placeholder | Result Example |
---|---|---|
Calendar year (2 digits) | yy | 23 |
Calendar year (4 digits) | yyyy | 2023 |
Month (1 digit) | M | 7 |
Month (2 digits) | MM | 07 |
Month (short name) | MMM | Jan, Feb, Dec |
Month (full name) | MMMM | January, February |
Day of month (1 digit) | d | 5, 23 |
Day of month (2 digits) | dd | 05, 23 |
Day of week (shortened) | E | Mon, Tue, Wed |
Day of week (full name) | EEEE | Monday, Tuesday |
AM, PM | a | AM, PM |
Hour (12-hour clock, 1 digit) | h | 1, 2, 10 |
Hour (12-hour clock, 2 digits) | hh | 01, 02, 10 |
Hour (24-hour clock, 1 digit) | H | 1, 2, 10, 23 |
Hour (24-hour clock, 2 digit) | HH | 01, 02, 10, 23 |
Minute (1 digit) | m | 1, 2, 3, 25, 30, 58 |
Minute (2 digit) | mm | 01, 02, 03, 24, 56 |
Second (1 digit) | s | 1, 2, 3, 10, 58 |
Second (2 digit) | ss | 01, 02, 10, 45 |
Parsing Dates
We commonly need to parse dates from strings when dealing with user input or data from external sources. date-fns provides the parse()
function for this purpose.
1 |
const dateString = '2023-07-15'; |
2 |
const parsedDate = dateFns.parse(dateString, 'yyyy-MM-dd', new Date()); |
3 |
console.log(parsedDate); // Output: Date object representing July 15, 2023 |
In this code, we parse the date from the dateString
using the format yyyy-MM-dd
, which corresponds to the provided date string. The third argument is the base date to use for calculating the parsed date. In this case, we use the current date as the base.
Adding and Subtracting Dates
Manipulating dates by adding or subtracting time intervals is a common requirement in date handling. date-fns provides a set of convenient functions to perform these operations with ease.
The following examples demonstrate the addDays()
and subDays()
functions:
1 |
const startDate = new Date(2023, 6, 15); // July 15, 2023 |
2 |
|
3 |
const fiveDaysLater = dateFns.addDays(startDate, 5); |
4 |
console.log(fiveDaysLater); // Output: Date object representing July 20, 2023 |
5 |
|
6 |
const threeDaysAgo = dateFns.subDays(startDate, 3); |
7 |
console.log(threeDaysAgo); // Output: Date object representing July 12, 2023 |
In this example, we start with the given startDate
of July 15, 2023. We then use the addDays()
function to calculate the date that is 5 days later, and we use the subDays()
function to find the date that was 3 days ago.
In addition to adding and subtracting days, date-fns provides functions for adding and subtracting months and years. As you'd expect, they are named addMonths()
, subMonths()
, addYears()
, and subYears()
.
When manipulating dates, it's essential to be aware of edge cases. For example, when subtracting months or years, the resulting date might not exist (e.g. February 30), and date-fns handles such cases intelligently by adjusting the date.
1 |
const startDate = new Date(2023, 0, 31); // January 31, 2023 |
2 |
|
3 |
const oneMonthLater = dateFns.addMonths(startDate, 1); |
4 |
console.log(oneMonthLater); // Output: Date object representing February 28, 2023 |
In this example that starts with January 31, 2023, adding one month results in February 28, 2023, since February does not have a 31st day.
Finding the Difference Between Dates
JavaScript's Date
object completely lacks the ability to find the difference between two Date
objects. Thankfully, date-fns has several functions you can use to find the difference between two Date
s. Some of them are:
Function Name | Purpose |
---|---|
differenceInMilliseconds() |
Get the number of milliseconds between the given dates. |
differenceInSeconds() |
Get the number of seconds between the given dates. |
differenceInMinutes() |
Get the number of minutes between the given dates. |
differenceInHours() |
Get the number of hours between the given dates. |
differenceInBusinessDays() |
Get the number of business days between the given dates. |
differenceInDays() |
Get the number of full days between the given dates. |
differenceInMonths() |
Get the number of months between the given dates. |
differenceInYears() |
Get the number of years between the given dates. |
There are many other "difference" functions, so be sure to check the documentation.
Consider the following example:
1 |
const startDate = new Date(2023, 6, 15); // July 15, 2023 |
2 |
const endDate = new Date(2023, 6, 22); // July 22, 2023 |
3 |
|
4 |
const daysDifference = dateFns.differenceInDays(endDate, startDate); |
5 |
console.log(daysDifference); // Output: 7 |
In this example, we use the differenceInDays()
function to calculate the number of days between startDate
and endDate
. The output is 7
.
Working With Time Zones
Working with time zones can be one of the most frustrating aspects of working with dates and times, but date-fns makes it easier with functions like utcToZonedTime()
and formatDistanceToNow()
. Consider the following example:
1 |
const utcDate = new Date(Date.UTC(2023, 6, 15, 12, 0, 0)); |
2 |
const timezone = 'America/New_York'; |
3 |
|
4 |
const zonedDate = dateFns.utcToZonedTime(utcDate, timezone); |
5 |
console.log(dateFns.formatDistanceToNow(zonedDate)); // Output: "6 months" |
In this example, we use the utcToZonedTime()
function to convert the utcDate
to the America/New_York
timezone. We then use the formatDistanceToNow()
function to get the time difference between the zoned date and the current time.
Handling Invalid Dates
We can never trust data that comes from the user, and it's generally good practice not to trust any data that you don't control. As such, we need to be able to check if a Date
is valid, and date-fns provides the isValid()
function for that purpose. For example:
1 |
const validDate = new Date(2023, 1, 30); // February 30, 2023 is not a valid date |
2 |
const invalidDate = new Date(NaN); // Invalid date |
3 |
|
4 |
console.log(dateFns.isValid(validDate)); // Output: true |
5 |
console.log(dateFns.isValid(invalidDate)); // Output: false |
This example creates both a valid and invalid Date
object. We then use the isValid()
function to determine if they are valid dates.
Conclusion
date-fns is a powerful and easy-to-use library that can save you a lot of time and effort when working with dates in JavaScript. This tutorial only scratched the surface of what the library can do, so be sure to explore the functionality and available options by checking out the official documentation.