date-fns の使い方 — JavaScript日付操作のモダンなユーティリティライブラリ
一言でいうと
date-fns は、JavaScript の Date オブジェクトを操作するための関数群を提供するユーティリティライブラリです。「日付版 Lodash」とも呼ばれ、200以上の純粋関数をツリーシェイキング可能な形で提供します。
どんな時に使う?
- 日付のフォーマット・パース —
2024-01-15を2024年1月15日(月)のように表示したい、またはその逆の変換をしたい場合 - 日付の計算・比較 — 「今日から30日後」「2つの日付の差分は何日か」「期間内かどうか」といった演算が必要な場合
- 国際化(i18n)対応の日付表示 — 日本語・英語など複数ロケールで日付をフォーマットしたい場合
インストール
# npm
npm install date-fns
# yarn
yarn add date-fns
# pnpm
pnpm add date-fns
本記事は date-fns v4.1.0 を基に執筆しています。v4 では第一級のタイムゾーンサポートが追加されています。
基本的な使い方
date-fns は必要な関数だけを個別にインポートして使います。ネイティブの Date オブジェクトをそのまま受け取り、新しい Date を返す純粋関数として設計されています。
import { format, addDays, differenceInDays, isAfter } from "date-fns";
import { ja } from "date-fns/locale";
// 日付のフォーマット
const today = new Date(2024, 5, 15); // 2024年6月15日
console.log(format(today, "yyyy-MM-dd"));
//=> '2024-06-15'
// 日本語ロケールでフォーマット
console.log(format(today, "yyyy年M月d日(EEEE)", { locale: ja }));
//=> '2024年6月15日(土曜日)'
// 日付の加算
const nextWeek = addDays(today, 7);
console.log(format(nextWeek, "yyyy-MM-dd"));
//=> '2024-06-22'
// 日付の差分
const start = new Date(2024, 0, 1);
const end = new Date(2024, 11, 31);
console.log(differenceInDays(end, start));
//=> 365
// 日付の比較
console.log(isAfter(end, start));
//=> true
よく使うAPIと使い方
1. format — 日付を文字列にフォーマット
最も使用頻度の高い関数です。フォーマットトークンは Unicode Technical Standard #35 に準拠しています。
import { format } from "date-fns";
import { ja } from "date-fns/locale";
const date = new Date(2024, 5, 15, 14, 30, 0);
// 基本的なフォーマット
format(date, "yyyy-MM-dd"); //=> '2024-06-15'
format(date, "yyyy/MM/dd HH:mm:ss"); //=> '2024/06/15 14:30:00'
format(date, "HH:mm"); //=> '14:30'
// 曜日・月名を含むフォーマット(英語)
format(date, "EEEE, MMMM do, yyyy"); //=> 'Saturday, June 15th, 2024'
// 日本語ロケール
format(date, "M月d日(E)", { locale: ja }); //=> '6月15日(土)'
// ISO 8601 週番号
format(date, "yyyy-'W'II"); //=> '2024-W24'
注意:
DDとdd、YYとyyは意味が異なります。ddは月の日、DDは年の日(1〜366)です。多くの場合ddとyyyyを使います。
2. parse / parseISO — 文字列を Date に変換
import { parse, parseISO } from "date-fns";
// ISO 8601 文字列のパース
const isoDate = parseISO("2024-06-15T14:30:00+09:00");
console.log(isoDate);
//=> Date オブジェクト(ローカルタイムゾーンに変換される)
// 任意のフォーマット文字列をパース
const parsed = parse("2024年06月15日", "yyyy年MM月dd日", new Date());
console.log(format(parsed, "yyyy-MM-dd"));
//=> '2024-06-15'
// 第3引数は参照日(パース結果に不足する情報を補完する基準)
const timeOnly = parse("14:30", "HH:mm", new Date(2024, 5, 15));
console.log(timeOnly);
//=> 2024-06-15T14:30:00 のDateオブジェクト
3. addDays / addMonths / subDays など — 日付の加減算
date-fns はイミュータブルなので、元の Date オブジェクトは変更されません。
import {
addDays,
addMonths,
addYears,
addHours,
subDays,
subMonths,
} from "date-fns";
const base = new Date(2024, 0, 31); // 2024-01-31
addDays(base, 1); //=> 2024-02-01
addMonths(base, 1); //=> 2024-02-29(うるう年を考慮)
addYears(base, 1); //=> 2025-01-31
addHours(base, 3); //=> 2024-01-31T03:00:00
subDays(base, 10); //=> 2024-01-21
subMonths(base, 1); //=> 2023-12-31
// 元のオブジェクトは変更されない
console.log(base); //=> 2024-01-31(そのまま)
4. differenceInDays / differenceInMonths など — 日付の差分計算
import {
differenceInDays,
differenceInMonths,
differenceInYears,
differenceInHours,
differenceInBusinessDays,
intervalToDuration,
} from "date-fns";
const start = new Date(2024, 0, 1);
const end = new Date(2024, 11, 31);
differenceInDays(end, start); //=> 365
differenceInMonths(end, start); //=> 11
differenceInYears(end, start); //=> 0
// 営業日(土日を除く)の差分
differenceInBusinessDays(end, start); //=> 261
// 時間単位の差分
const morning = new Date(2024, 5, 15, 9, 0);
const evening = new Date(2024, 5, 15, 18, 30);
differenceInHours(evening, morning); //=> 9
// 年・月・日・時・分・秒に分解
const duration = intervalToDuration({ start, end });
console.log(duration);
//=> { years: 0, months: 11, days: 30, hours: 0, minutes: 0, seconds: 0 }
5. isValid / isBefore / isAfter / isWithinInterval — 日付の検証・比較
import {
isValid,
isBefore,
isAfter,
isEqual,
isWithinInterval,
isWeekend,
isFuture,
isPast,
} from "date-fns";
// バリデーション
isValid(new Date(2024, 5, 15)); //=> true
isValid(new Date("invalid")); //=> false
isValid(new Date(NaN)); //=> false
// 比較
const dateA = new Date(2024, 0, 1);
const dateB = new Date(2024, 11, 31);
isBefore(dateA, dateB); //=> true
isAfter(dateA, dateB); //=> false
isEqual(dateA, dateA); //=> true
// 範囲内チェック
const target = new Date(2024, 5, 15);
isWithinInterval(target, { start: dateA, end: dateB }); //=> true
// ユーティリティ
isWeekend(new Date(2024, 5, 15)); //=> true(土曜日)
isFuture(new Date(2099, 0, 1)); //=> true
isPast(new Date(2000, 0, 1)); //=> true
類似パッケージとの比較
| 特徴 | date-fns | Day.js | Luxon | Moment.js |
|---|---|---|---|---|
| バンドルサイズ(最小構成) | 関数単位で極小 | ~2KB | ~23KB | ~72KB |
| ツリーシェイキング | ✅ 完全対応 | ⚠️ プラグイン単位 | ❌ | ❌ |
| イミュータブル | ✅ | ✅ | ✅ | ❌ |
| TypeScript | ✅ ネイティブ | ✅ | ✅ | ⚠️ @types |
| ネイティブ Date 使用 | ✅ | ❌(ラッパー) | ❌(ラッパー) | ❌(ラッパー) |
| タイムゾーン(v4) | ✅ 組み込み | プラグイン | ✅ 組み込み | プラグイン |
| メンテナンス状況 | ✅ 活発 | ✅ 活発 | ✅ 活発 | ⛔ 非推奨 |
| 関数数 | 200+ | 少なめ | 中程度 | 多い |
選定の指針:
- バンドルサイズを最小化したい → date-fns(ツリーシェイキングで使う関数だけバンドル)
- チェーンメソッドが好み → Day.js / Luxon
- ネイティブ Date をそのまま扱いたい → date-fns
注意点・Tips
フォーマットトークンの大文字・小文字に注意
import { format } from "date-fns";
const date = new Date(2024, 0, 7);
// ❌ よくある間違い
format(date, "YYYY-MM-DD"); // 意図しない結果になる可能性あり
// ✅ 正しい
format(date, "yyyy-MM-dd"); // '2024-01-07'
yyyy は暦年、YYYY はISO週番号年です。年末年始で値がずれることがあります。同様に dd は月の日、DD は年の日です。
ロケールはバンドルサイズに影響する
// ❌ 全ロケールをインポートしない
// import * as locales from "date-fns/locale";
// ✅ 必要なロケールだけインポート
import { ja } from "date-fns/locale";
import { enUS } from "date-fns/locale";
v4 のタイムゾーンサポート
v4 からは date-fns/tz でタイムゾーン操作が組み込みでサポートされています。
import { TZDate } from "date-fns/tz";
import { format, addHours } from "date-fns";
// タイムゾーン付きの日付を作成
const tokyoDate = new TZDate(2024, 5, 15, 12, 0, 0, "Asia/Tokyo");
const nyDate = new TZDate(2024, 5, 15, 12, 0, 0, "America/New_York");
// 通常の date-fns 関数がそのまま使える
console.log(format(tokyoDate, "yyyy-MM-dd HH:mm:ss zzz"));
console.log(format(addHours(tokyoDate, 3), "HH:mm"));
month は 0 始まり
JavaScript の Date コンストラクタと同様に、月は 0 始まり(0 = 1月、11 = 12月)です。
// 2024年6月15日を作る場合
new Date(2024, 5, 15); // 月は 5(= 6月)
Invalid Date のハンドリング
import { isValid, parse } from "date-fns";
const result = parse("not-a-date", "yyyy-MM-dd", new Date());
if (!isValid(result)) {
console.error("無効な日付です");
}
パースに失敗すると Invalid Date が返ります。必ず isValid でチェックしてから後続処理に渡しましょう。
まとめ
date-fns は、ネイティブの Date オブジェクトをイミュータブルかつ関数型のスタイルで操作できる、JavaScript 日付操作ライブラリの決定版です。ツリーシェイキングによるバンドルサイズの最適化、完全な TypeScript サポート、そして v4 で追加されたタイムゾーンの組み込みサポートにより、モダンなWebアプリケーション開発において最も実用的な選択肢の一つといえます。