본문으로 건너뛰기 date-fns Complete Guide | Modern JavaScript Date Utility Library

date-fns Complete Guide | Modern JavaScript Date Utility Library

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:

  1. Import only what you need
  2. All functions are immutable
  3. Use formatISO for storage
  4. date-fns-tz for time zones
  5. 200+ utility functions

Next Steps:

  • Try Day.js
  • Learn Lodash
  • Build with TypeScript

Resources: