date-fns Complete Guide | Modern JavaScript Date Utility Library
이 글의 핵심
date-fns is a modern JavaScript date utility library with over 200 functions. It's modular, immutable, tree-shakeable, and provides excellent TypeScript support.
Introduction
date-fns provides comprehensive utilities for JavaScript dates. Unlike Moment.js, it’s modular and tree-shakeable, meaning you only import what you need.
Why date-fns?
// Moment.js (legacy, not recommended)
moment().add(7, 'days').format('YYYY-MM-DD');
// Bundle size: ~70KB
// date-fns (modern, recommended)
import { addDays, format } from 'date-fns';
format(addDays(new Date(), 7), 'yyyy-MM-dd');
// Bundle size: ~2-5KB (only what you import!)
1. Installation
npm install date-fns
2. Basic Usage
Formatting Dates
import { format } from 'date-fns';
const date = new Date(2024, 0, 15); // January 15, 2024
format(date, 'yyyy-MM-dd'); // "2024-01-15"
format(date, 'MMMM do, yyyy'); // "January 15th, 2024"
format(date, 'h:mm a'); // "12:00 AM"
format(date, "EEEE 'at' h:mm a"); // "Monday at 12:00 AM"
Parsing Dates
import { parse, parseISO } from 'date-fns';
// Parse ISO string
parseISO('2024-01-15'); // Date object
// Parse custom format
parse('15/01/2024', 'dd/MM/yyyy', new Date());
parse('Jan 15, 2024', 'MMM dd, yyyy', new Date());
3. Date Arithmetic
import { addDays, addMonths, addYears, subDays, subMonths } from 'date-fns';
const date = new Date(2024, 0, 15);
// Addition
addDays(date, 7); // January 22, 2024
addMonths(date, 3); // April 15, 2024
addYears(date, 1); // January 15, 2025
// Subtraction
subDays(date, 7); // January 8, 2024
subMonths(date, 1); // December 15, 2023
// All functions return NEW date (immutable)
const original = new Date(2024, 0, 15);
const modified = addDays(original, 7);
console.log(original); // Still January 15, 2024
console.log(modified); // January 22, 2024
4. Comparison
import {
isAfter,
isBefore,
isEqual,
isFuture,
isPast,
isToday,
isYesterday,
isTomorrow,
isWeekend,
} from 'date-fns';
const date1 = new Date(2024, 0, 15);
const date2 = new Date(2024, 0, 20);
isAfter(date2, date1); // true
isBefore(date1, date2); // true
isEqual(date1, date1); // true
isFuture(new Date(2025, 0, 1)); // true
isPast(new Date(2020, 0, 1)); // true
isToday(new Date()); // true
isWeekend(new Date(2024, 0, 13)); // true (Saturday)
5. Difference Calculations
import {
differenceInDays,
differenceInMonths,
differenceInYears,
differenceInHours,
differenceInMinutes,
} from 'date-fns';
const start = new Date(2024, 0, 1);
const end = new Date(2024, 0, 15);
differenceInDays(end, start); // 14
differenceInHours(end, start); // 336
differenceInMinutes(end, start); // 20160
const birthDate = new Date(1990, 0, 1);
differenceInYears(new Date(), birthDate); // 34
6. Start/End of Period
import {
startOfDay,
endOfDay,
startOfWeek,
endOfWeek,
startOfMonth,
endOfMonth,
startOfYear,
endOfYear,
} from 'date-fns';
const date = new Date(2024, 0, 15, 14, 30); // Jan 15, 2:30 PM
startOfDay(date); // Jan 15, 12:00:00 AM
endOfDay(date); // Jan 15, 11:59:59 PM
startOfWeek(date); // Jan 14 (Sunday)
endOfWeek(date); // Jan 20 (Saturday)
startOfMonth(date); // Jan 1
endOfMonth(date); // Jan 31
startOfYear(date); // Jan 1
endOfYear(date); // Dec 31
7. Internationalization
npm install date-fns
import { format } from 'date-fns';
import { ko, ja, es, fr } from 'date-fns/locale';
const date = new Date(2024, 0, 15);
// English (default)
format(date, 'PPPP');
// "Monday, January 15th, 2024"
// Korean
format(date, 'PPPP', { locale: ko });
// "2024년 1월 15일 월요일"
// Japanese
format(date, 'PPPP', { locale: ja });
// "2024年1月15日月曜日"
// Spanish
format(date, 'PPPP', { locale: es });
// "lunes, 15 de enero de 2024"
8. Time Zones
npm install date-fns date-fns-tz
import { format } from 'date-fns';
import { formatInTimeZone, utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';
const date = new Date('2024-01-15T12:00:00Z');
// Format in specific timezone
formatInTimeZone(date, 'America/New_York', 'yyyy-MM-dd HH:mm:ss zzz');
// "2024-01-15 07:00:00 EST"
formatInTimeZone(date, 'Asia/Seoul', 'yyyy-MM-dd HH:mm:ss zzz');
// "2024-01-15 21:00:00 KST"
// Convert UTC to timezone
const newYorkDate = utcToZonedTime(date, 'America/New_York');
// Convert timezone to UTC
const utcDate = zonedTimeToUtc('2024-01-15 12:00:00', 'America/New_York');
9. Validation
import { isValid, isDate, isMatch } from 'date-fns';
isValid(new Date()); // true
isValid(new Date('invalid')); // false
isDate(new Date()); // true
isDate('2024-01-15'); // false
isMatch('2024-01-15', 'yyyy-MM-dd'); // true
isMatch('15/01/2024', 'yyyy-MM-dd'); // false
10. Real-World Examples
Relative Time Display
import { formatDistanceToNow } from 'date-fns';
const postDate = new Date(2024, 0, 14);
formatDistanceToNow(postDate, { addSuffix: true });
// "1 day ago"
const futureDate = new Date(2024, 0, 20);
formatDistanceToNow(futureDate, { addSuffix: true });
// "in 5 days"
Date Range Filtering
import { isWithinInterval } from 'date-fns';
const rangeStart = new Date(2024, 0, 1);
const rangeEnd = new Date(2024, 0, 31);
const testDate = new Date(2024, 0, 15);
isWithinInterval(testDate, { start: rangeStart, end: rangeEnd });
// true
Business Days
import { addBusinessDays, isWeekend, differenceInBusinessDays } from 'date-fns';
const date = new Date(2024, 0, 15); // Monday
addBusinessDays(date, 5); // Next Monday (skips weekend)
differenceInBusinessDays(
new Date(2024, 0, 22),
new Date(2024, 0, 15)
); // 5 business days
Age Calculator
import { differenceInYears, differenceInMonths, differenceInDays } from 'date-fns';
function calculateAge(birthDate) {
const now = new Date();
const years = differenceInYears(now, birthDate);
const months = differenceInMonths(now, birthDate) % 12;
return { years, months };
}
calculateAge(new Date(1990, 0, 15));
// { years: 34, months: 0 }
Event Countdown
import { intervalToDuration, formatDuration } from 'date-fns';
function countdown(eventDate) {
const duration = intervalToDuration({
start: new Date(),
end: eventDate,
});
return formatDuration(duration);
}
countdown(new Date(2024, 11, 25));
// "11 months 10 days 3 hours 25 minutes"
11. Best Practices
1. Always Import Specific Functions
// Good: tree-shakeable
import { format, addDays } from 'date-fns';
// Bad: imports everything
import * as dateFns from 'date-fns';
2. Use ISO Format for Storage
import { formatISO, parseISO } from 'date-fns';
// Store dates as ISO strings
const dateString = formatISO(new Date());
// "2024-01-15T12:00:00.000Z"
// Parse back to Date
const date = parseISO(dateString);
3. Handle Invalid Dates
import { isValid, parse } from 'date-fns';
function parseDate(dateString, formatString) {
const parsed = parse(dateString, formatString, new Date());
if (!isValid(parsed)) {
throw new Error('Invalid date');
}
return parsed;
}
12. Performance Tips
// Create reusable formatter
import { format } from 'date-fns';
const formatDate = (date) => format(date, 'yyyy-MM-dd');
// Use once, reuse many times
dates.map(formatDate);
Summary
date-fns is the modern choice for date manipulation:
- Modular - tree-shakeable, small bundle
- Immutable - pure functions
- TypeScript - full type support
- i18n - 100+ locales
- Time zones with date-fns-tz
Key Takeaways:
- Import only what you need
- All functions are immutable
- Use formatISO for storage
- date-fns-tz for time zones
- 200+ utility functions
Next Steps:
- Try Day.js
- Learn Lodash
- Build with TypeScript
Resources: