date-fns is a modern JavaScript library for working with dates and times. It provides a large set of functions that let you manipulate dates, format them, and perform calculations. The library is modular, meaning you can import only the functions you need, which helps keep your bundle size small.
In this blog post, we'll take a closer look at some of the functions date-fns provides. This is not a complete overview of every method in the library. See the official documentation for more details and a complete list of available methods.
date-fns is a collection of independent date and time functions that you import into your application individually.
date-fns doesn't provide a date/time wrapper, and it doesn't add methods to the built-in Date object.
Instead, it works with the native Date object and provides functions that accept Date objects or numbers as parameters.
Parameters ¶
Almost all methods in the library accept either a Date object or a number as a parameter. Internally, date-fns converts these parameters to a Date object using the toDate function. If you have a date string, convert it manually with parseISO.
import { parseISO, toDate } from 'date-fns';
const today = new Date();
const d1 = toDate(today);
const d2 = toDate(1515421707921);
const d3 = parseISO('2018-01-11T03:30:03');
// d1 = Mon Jan 08 2018 15:30:09 GMT+0100 (W. Europe Standard Time)
// d2 = Mon Jan 08 2018 15:28:27 GMT+0100 (W. Europe Standard Time)
// d3 = Thu Jan 11 2018 03:30:03 GMT+0100 (W. Europe Standard Time)
The toDate function returns a clone when a Date object is passed to it. All functions in date-fns are immutable and don't modify their parameters. When a number is passed to the function, it's treated as the number of milliseconds elapsed since January 1, 1970, 00:00:00 UTC.
When you have functions that expect multiple parameters, you can provide arguments of the same type or mix different types.
import { isAfter, parseISO } from 'date-fns';
isAfter(new Date(2016, 11, 31), new Date(2017, 11, 31));
isAfter(1515422016315, 1515422016316);
isAfter(1515422016315, new Date(2017, 11, 31));
isAfter(new Date(2018, 0, 10), parseISO('2018-01-11T03:30:03'));
isAfter(1515422016315, parseISO('2018-01-11T03:30:03'));
Time Units ¶
Instead of providing one function that supports multiple time units, date-fns provides variants for each unit. For example, there are addMilliseconds, addSeconds, addMinutes, addHours, addDays, addWeeks, addMonths, addQuarters, addYears, and addISOWeekYears.
Not every function supports every time unit.
Parsing and Formatting ¶
Converting a string to a Date object and vice versa is a common task in applications. To convert a string into a Date, date-fns provides parse.
parse requires three parameters: the input string, the format string, and baseDate. The function returns a Date object when parsing succeeds.
import { parse } from 'date-fns';
const result = parse('31.01.2018', 'dd.MM.yyyy', new Date());
// Wed Jan 31 2018 00:00:00 GMT+0100
parse supports a wide variety of format tokens. See the official documentation for a complete overview.
The third parameter (baseDate) is used when you parse partial dates, as in this example.
const result = parse('January 2nd', 'MMMM do', new Date());
// Tue Jan 02 2018 00:00:00 GMT+0100 (W. Europe Standard Time)
The year is taken from the third parameter.
To convert a Date to a string, use format. The format string (second parameter) supports the same tokens as parse.
import { format, getDayOfYear, parseISO } from 'date-fns';
const result = format(new Date(2018, 0, 15), 'MM/dd/yyyy');
// 01/15/2018
const result = format(1515424147742, 'MMMM do, yyyy');
// January 8th, 2018
const dayOfYear = getDayOfYear(parseISO('2018-06-15T11:30:00'));
// 166
Set and Get ¶
The set* and get* functions set a time unit to a specific value and retrieve a time unit's value, respectively. As mentioned before, date-fns doesn't mutate parameters, so set* functions always return a new Date object.
import { getMilliseconds, getMinutes, getYear, parseISO } from 'date-fns';
let result = getMinutes(parseISO('2018-01-15T11:33:44.987'));
// 33
result = getMilliseconds(parseISO('2018-01-15T11:33:44.987'));
// 987
result = getYear(parseISO('2018-01-15T11:33:44.987'));
// 2018
import { parseISO, setMonth, setQuarter, setSeconds } from 'date-fns';
let result = setSeconds(1515424816229, 55);
// Mon Jan 08 2018 16:20:55 GMT+0100 (W. Europe Standard Time)
result = setQuarter(new Date(2018, 0, 15), 3);
// Sun Jul 15 2018 00:00:00 GMT+0200 (W. Europe Summer Time)
result = setMonth(parseISO('2018-01-15T11:33:44.987'), 6);
// Sun Jul 15 2018 11:33:44 GMT+0200 (W. Europe Summer Time)
Note that months are 0-based, and quarters start with 1.
Comparing ¶
date-fns provides comparison functions like isAfter, isBefore, and isEqual, which check whether the first date is after, before, or equal to the second date.
import { isAfter, parseISO } from 'date-fns';
let result = isAfter(new Date(2018, 0, 15), parseISO('2018-01-16'));
// false
result = isAfter(parseISO('2018-01-16'), new Date(2018, 0, 15));
// true
import { isBefore, parseISO } from 'date-fns';
let result = isBefore(1515424147742, 1515424147744);
// true
result = isBefore(parseISO('2018-01-16'), parseISO('2018-01-17'));
// true
import { isEqual, parseISO } from 'date-fns';
let result = isEqual(1515424147742, 1515424147742);
// true
result = isEqual(new Date(2018, 0, 15), parseISO('2018-01-15'));
// true
result = isEqual(new Date(2018, 0, 15), new Date(2018, 0, 16));
// false
For specific units, isSame* functions exist that check whether the specific unit is the same in two dates.
import { isSameHour, isSameMonth, isSameWeek, parseISO } from 'date-fns';
let result = isSameWeek(new Date(2018, 0, 15), parseISO('2018-01-16'));
//true
result = isSameHour(1515424147742, 1515414137199);
//false
result = isSameMonth(parseISO('2018-01-01'), parseISO('2018-01-31'));
//true
Arithmetic ¶
The add* and sub* functions add and subtract a certain amount of a specific unit. Like set* functions, they don't modify the provided parameter; they return a new Date object.
import { addMinutes, addWeeks, addYears, parseISO } from 'date-fns';
let result = addWeeks(new Date(2018, 0, 15), 2);
//Mon Jan 29 2018 00:00:00 GMT+0100 (W. Europe Standard Time)
result = addMinutes(1515424147742, 60);
//Mon Jan 08 2018 17:09:07 GMT+0100 (W. Europe Standard Time)
result = addYears(parseISO('2018-01-01'), 5);
//Sun Jan 01 2023 00:00:00 GMT+0100 (W. Europe Standard Time)
import {
getMilliseconds,
parseISO,
subMilliseconds,
subQuarters,
subSeconds
} from 'date-fns';
let result = subSeconds(parseISO('2018-01-31T11:55:44.987'), 6);
//Wed Jan 31 2018 11:55:38 GMT+0100 (W. Europe Standard Time)
result = subQuarters(parseISO('2018-01-31T11:55:44.987'), 1);
//Tue Oct 31 2017 11:55:44 GMT+0100 (W. Europe Standard Time)
result = subMilliseconds(parseISO('2018-01-31T11:55:44.987'), 187);
const ms = getMilliseconds(result);
//800
Weekdays ¶
For weekdays, some special functions return the weekday and check if a date falls on a specific weekday. The getDay function returns a number between 0 (Sunday) and 6 (Saturday). For each weekday, an is* function exists, as well as isWeekend to check if a date falls on a weekend (Saturday or Sunday).
import { getDay, isMonday, isWeekend } from 'date-fns';
let result = getDay(new Date(2018, 0, 8));
//1
result = isMonday(new Date(2018, 0, 8));
//true
result = isWeekend(new Date(2018, 0, 8));
//false
Intervals ¶
date-fns supports an interval type that combines two dates. An interval object has two properties: start and end. Both properties can hold a Date or a number.
import { parseISO } from 'date-fns';
const interval1 = {start: parseISO('2018-01-01'), end: parseISO('2018-01-15')};
const interval2 = {start: new Date(2018, 0, 14), end: 1517353200000};
date-fns provides four functions that use intervals as parameters:
areIntervalsOverlapping: checks if two intervals overlap.
import { areIntervalsOverlapping } from 'date-fns';
const result = areIntervalsOverlapping(interval1, interval2);
// true
eachDayOfInterval: returns an array of dates with each day of the interval.
import { eachDayOfInterval } from 'date-fns';
const result = eachDayOfInterval(interval1);
/*
[
Mon Jan 01 2018 00:00:00 GMT+0100 (W. Europe Standard Time),
Tue Jan 02 2018 00:00:00 GMT+0100 (W. Europe Standard Time)],
....
Mon Jan 15 2018 00:00:00 GMT+0100 (W. Europe Standard Time)
]
*/
getOverlappingDaysInIntervals: returns the number of days that two intervals overlap.
import { getOverlappingDaysInIntervals } from 'date-fns';
const result = getOverlappingDaysInIntervals(interval1, interval2);
// 1
isWithinInterval: checks if a date is within an interval.
import { isWithinInterval, parseISO } from 'date-fns';
const result = isWithinInterval(parseISO('2018-01-02'), interval1);
// true
Difference ¶
The difference* functions return the difference between two dates in a specific unit.
import { differenceInSeconds } from 'date-fns';
const result = differenceInSeconds(1515429928956, 1515429922956);
// 6
For days, weeks, months, quarters, and years, two functions calculate the difference. The differenceInCalendar* functions only consider the specific unit and return the difference. The other differenceIn* functions return the difference in full days, weeks, months, quarters, and years. For instance, differenceInDays calculates how many full days (24 hours) are between the two dates.
import {
differenceInCalendarMonths,
differenceInMonths,
parseISO
} from 'date-fns';
let result = differenceInMonths(parseISO('2018-03-15'), parseISO('2018-01-17'));
//1
result = differenceInCalendarMonths(parseISO('2018-03-15'), parseISO('2018-01-17'));
//2
import {
differenceInCalendarDays,
differenceInDays,
parseISO
} from 'date-fns';
let result = differenceInDays(parseISO('2018-01-03T09:45:00'), parseISO('2018-01-01T11:30:00'));
// 1
result = differenceInCalendarDays(parseISO('2018-01-03T09:45:00'), parseISO('2018-01-01T11:30:00'));
// 2
Another everyday use case is representing the difference between two dates in words, like "3 days" or "in 20 minutes". For this use case, date-fns provides three functions.
formatDistance
import { formatDistance, parseISO } from 'date-fns';
let result = formatDistance(parseISO('2018-01-15'), parseISO('2018-01-01'));
//14 days
result = formatDistance(parseISO('2018-01-01'), parseISO('2019-04-01'));
//over 1 year
result = formatDistance(parseISO('2018-02-01'), parseISO('2018-01-01'));
//about 1 month
The function adds the word 'ago' and 'in' when addSuffix is set to true.
const result = formatDistance(new Date(2018, 7, 1), new Date(2018, 0, 1), {addSuffix: true});
//in 7 months
const result = formatDistance(new Date(2018, 0, 1), new Date(2018, 0, 15), {addSuffix: true});
//14 days ago
When includeSeconds is true, the string contains a more detailed message when the difference is less than a minute.
const result = formatDistance(1515424149742, 1515424147742);
//less than a minute
const result = formatDistance(1515424149742, 1515424147742, {includeSeconds: true});
//less than 5 seconds
formatDistanceStrict: like formatDistance, but it does not add words such as 'almost', 'over', or 'less than'.
import { formatDistanceStrict, parseISO } from 'date-fns';
let result = formatDistanceStrict(parseISO('2018-01-15'), parseISO('2018-01-01'));
//14 days
result = formatDistanceStrict(parseISO('2018-01-01'), parseISO('2019-04-01'));
//1 year
result = formatDistanceStrict(parseISO('2018-02-01'), parseISO('2018-01-01'));
//1 month
formatRelative: This function returns a string for the last and next 6 days, like 'last Sunday', 'yesterday', 'Tuesday'. For all other dates, it returns MM/dd/yyyy.
import { formatRelative } from 'date-fns';
let result = formatRelative(new Date(2018, 0, 4), new Date(2018, 0, 8));
//last Thursday at 12:00 a.m.
result = formatRelative(new Date(2018, 0, 7), new Date(2018, 0, 8));
//yesterday at 12:00 a.m.
result = formatRelative(new Date(2018, 0, 9), new Date(2018, 0, 8));
//tomorrow at 12:00 a.m.
result = formatRelative(new Date(2018, 0, 10), new Date(2018, 0, 8));
//Wednesday at 12:00 a.m.
result = formatRelative(new Date(2018, 0, 20), new Date(2018, 0, 8));
//01/20/2018
Internationalization ¶
The library contains translations for many languages. See the documentation for a list of all currently supported languages.
To use a translation, you need to import the locale object.
import { fr } from 'date-fns/locale';
Then pass it as an option to a function:
import { formatDistance } from 'date-fns';
const result = formatDistance(
new Date(2018, 0, 15),
new Date(2018, 0, 1),
{locale: fr, addSuffix: true}
);
// dans 14 jours
Only format, parse, formatDistance, formatDistanceStrict, and formatRelative support internationalization.
Time Zones ¶
The biggest feature added in date-fns v4 is first-class time-zone support. Use @date-fns/tz with the in option to make calculations in a specific time zone.
import { addDays, formatISO, startOfDay } from 'date-fns';
import { tz } from '@date-fns/tz';
const singapore = tz('Asia/Singapore');
const result = startOfDay(addDays(new Date(), 5), { in: singapore });
console.log(formatISO(result));
// 2026-03-08T00:00:00+08:00 (example output)
This is particularly useful when your users, backend, and business rules operate in different time zones.