date-fns vs dayjs vs moment vs luxon vs datejs
JavaScript 日付操作ライブラリの技術的比較
date-fnsdayjsmomentluxondatejs類似パッケージ:
JavaScript 日付操作ライブラリの技術的比較

date-fnsdatejsdayjsluxonmoment はすべて JavaScript で日付と時刻を扱うためのライブラリです。これらは日付のパース、フォーマット、操作、国際化などの共通機能を提供しますが、設計思想、API スタイル、モジュール性、タイムゾーン対応、メンテナンス状況において大きく異なります。特に momentdatejs は公式に非推奨とされており、新規プロジェクトでの使用は避けるべきです。一方、date-fnsdayjsluxon は現代的なフロントエンド開発に適した選択肢として活用されています。

npmのダウンロードトレンド
3 年
GitHub Starsランキング
統計詳細
パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
date-fns45,984,34536,44922.6 MB9061年前MIT
dayjs35,842,75948,540679 kB1,1883ヶ月前MIT
moment28,121,96248,0754.35 MB2902年前MIT
luxon20,678,84616,3504.59 MB1925ヶ月前MIT
datejs37,399354-3811年前MIT

JavaScript 日付ライブラリ深掘り:date-fns、datejs、dayjs、luxon、moment

フロントエンド開発で日付を扱うのは一見簡単ですが、タイムゾーン、ロケール、パフォーマンス、メンテナンス性など、実際には多くの課題があります。ここでは、代表的な5つの日付ライブラリを技術的に比較し、どの場面でどれを選ぶべきかを明らかにします。

⚠️ 非推奨ライブラリの現状

まず重要な前提として、datejsmoment公式に非推奨 とされています。

  • datejs: npm ページ および GitHub で「このプロジェクトはメンテナンスされていません」と明記されています。最後のリリースは2007年であり、新規プロジェクトでの使用は避けてください。
  • moment: 公式サイト および npm ページ で「プロジェクトはレガシー状態」とされ、「新しいプロジェクトでは他のライブラリを検討してください」と記載されています。

以下では、これらの非推奨ライブラリも含めて技術的比較を行いますが、新規採用は推奨されません。

📅 基本的な日付作成とフォーマット

date-fns

関数型スタイルで、各操作が独立した関数です。不変性が保たれます。

import { format, addDays } from 'date-fns';
import { ja } from 'date-fns/locale';

const now = new Date();
const tomorrow = addDays(now, 1);
const formatted = format(tomorrow, 'yyyy年MM月dd日 EEEE', { locale: ja });
// 例: "2024年06月15日 土曜日"

datejs(非推奨)

ミュータブルな拡張メソッドを Date オブジェクトに追加します。

// datejs は Date.prototype を拡張する
Date.today().add({ days: 1 }).toString('yyyy年MM月dd日');

dayjs

チェーン可能な API で、moment に似ていますが軽量です。

import dayjs from 'dayjs';
import 'dayjs/locale/ja';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(localizedFormat);
dayjs.locale('ja');

const formatted = dayjs().add(1, 'day').format('YYYY年MM月DD日 dddd');
// 例: "2024年06月15日 土曜日"

luxon

DateTime オブジェクトを使用し、Intl API に依存します。

import { DateTime } from 'luxon';

const formatted = DateTime.now()
  .plus({ days: 1 })
  .setLocale('ja')
  .toFormat('yyyy年MM月dd日 cccc');
// 例: "2024年06月15日 土曜日"

moment(非推奨)

チェーン可能ですが、内部でミュータブルな操作を行うことがあります。

import moment from 'moment';
import 'moment/locale/ja';
moment.locale('ja');

const formatted = moment().add(1, 'days').format('YYYY年MM月DD日 dddd');

🌍 タイムゾーン対応

タイムゾーン処理は多くのアプリケーションで重要です。各ライブラリの対応状況は大きく異なります。

date-fns

コアにはタイムゾーン機能が含まれていません。date-fns-tz という別パッケージが必要です。

import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz';

const utcDate = zonedTimeToUtc('2024-06-15 12:00:00', 'Asia/Tokyo');
const tokyoTime = utcToZonedTime(utcDate, 'Asia/Tokyo');
const formatted = format(tokyoTime, 'yyyy-MM-dd HH:mm:ss XXX', { timeZone: 'Asia/Tokyo' });

datejs(非推奨)

タイムゾーンサポートは限定的で、信頼性に欠けます。

// datejs はタイムゾーンを正しく扱えません
Date.parse('2024-06-15T12:00:00+09:00'); // 危険

dayjs

timezone プラグインを有効にする必要があります。

import dayjs from 'dayjs';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
dayjs.extend(utc);
dayjs.extend(timezone);

const tokyoTime = dayjs().tz('Asia/Tokyo').format();

luxon

ネイティブで強力なタイムゾーンサポート。Intl API を直接利用するため、ブラウザのタイムゾーンデータに依存します。

import { DateTime } from 'luxon';

const tokyoTime = DateTime.now().setZone('Asia/Tokyo').toISO();
// 例: "2024-06-15T12:00:00.000+09:00"

moment(非推奨)

moment-timezone という別パッケージが必要で、バンドルサイズが膨大になります。

import moment from 'moment-timezone';

const tokyoTime = moment().tz('Asia/Tokyo').format();

📦 モジュール性とバンドルサイズ

date-fns

各関数が独立しているため、未使用のコードはビルド時に完全に削除されます(ツリーシェイキング)。最小限の機能しか使わない場合、非常に軽量になります。

dayjs

コアは極小(約2KB)で、必要な機能だけをプラグインとして追加できます。ツリーシェイキングにも対応しています。

luxon

単一のモジュールですが、ESM 対応により未使用のエクスポートは削除可能です。ただし、Intl API への依存があるため、機能自体はブラウザに委ねられます。

moment / datejs

全体をインポートする必要があり、ツリーシェイキングが効きません。特に moment はロケールデータを含めると数十KBになります。

🔁 ミュータブル vs 不変性

  • date-fns: 完全に不変。元の Date オブジェクトは変更されません。
  • dayjs: 不変。新しいインスタンスを返します。
  • luxon: 不変。新しい DateTime インスタンスを返します。
  • moment: 表面上は不変に見えますが、内部でミュータブルな操作を行うことがあり、予期しない副作用を引き起こす可能性があります。
  • datejs: Date オブジェクトを直接拡張・変更するため、完全にミュータブルです。これは大規模アプリではバグの温床になります。

🌐 国際化(i18n)対応

date-fns

各ロケールが個別のファイルとして提供され、必要に応じてインポートします。

import { format } from 'date-fns';
import { ja } from 'date-fns/locale';
format(date, 'PPPP', { locale: ja });

dayjs

ロケールはプラグインとして提供され、動的ロードも可能です。

import 'dayjs/locale/ja';
dayjs.locale('ja');

luxon

ブラウザの Intl API に依存するため、OS やブラウザがサポートするロケールがそのまま利用できます。追加のロケールファイル不要。

DateTime.now().setLocale('ja-JP').toFormat('D');

moment / datejs

ロケールデータを手動でインポートする必要があり、バンドルサイズに悪影響を与えます。

✅ 結論:どのライブラリを選ぶべきか?

要件推奨ライブラリ
最小限のバンドルサイズ、関数型スタイル、不変性重視date-fns
moment に似た使いやすさ、軽量さ、プラグイン拡張性dayjs
正確なタイムゾーン処理、ネイティブな国際化対応luxon
新規プロジェクトdatejsmoment は使用禁止

最終的なアドバイス

  • 新規プロジェクトでは、date-fnsdayjsluxon のいずれかを選んでください。
  • シンプルな日付操作が中心なら dayjs がバランスが良いです。
  • 複雑なタイムゾーンやロケール要件があるなら luxon が最も堅牢です。
  • 関数型プログラミングを好む、または 極限までバンドルサイズを削減したいなら date-fns が最適です。

これらの選択は、あなたのアプリケーションの規模、ユーザーの地理的分布、パフォーマンス要件、そしてチームの開発哲学によって決まるべきです。

選び方: date-fns vs dayjs vs moment vs luxon vs datejs
  • date-fns:

    date-fns は関数型アプローチを採用し、各機能が独立した関数として提供されるため、ツリーシェイキングとの相性が非常に良いです。不変性を保ち、軽量なバンドルを目指すモダンなビルド環境(例:Vite、Webpack)で最適です。ただし、タイムゾーン処理には追加の設定や Intl API への依存が必要です。

  • dayjs:

    dayjsmoment に似たチェーン可能な API を持ちながら、極めて軽量で高速です。プラグインによる拡張性も高く、基本機能に加えてタイムゾーンやカスタムパースなどを必要に応じて追加できます。シンプルな日付操作が中心で、バンドルサイズを厳しく制限したいプロジェクトに最適です。

  • moment:

    moment はかつて事実上の標準でしたが、公式ドキュメントおよび npm ページで「レガシー」として非推奨とされています。巨大なバンドルサイズ、ミュータブルな API、モダンな JavaScript のベストプラクティスに合わない設計が理由です。新規プロジェクトでは使用せず、既存コードの維持または段階的な移行のみを想定してください。

  • luxon:

    luxon は Intl API を基盤に構築されており、ネイティブなタイムゾーンやロケール対応が強力です。オブジェクト指向でチェーン可能な API を提供し、複雑な国際化要件や正確なタイムゾーン計算が必要なアプリケーションに向いています。ただし、古いブラウザではポリフィルが必要になる場合があります。

  • datejs:

    datejs は長年メンテナンスされておらず、npm ページおよび GitHub リポジトリで公式に非推奨(deprecated)と明記されています。新規プロジェクトでは絶対に使用しないでください。既存システムで使われている場合は、date-fnsdayjs への移行を検討すべきです。

date-fns のREADME

🔥️ NEW: date-fns v4.0 with first-class time zone support is out!

date-fns

date-fns provides the most comprehensive, yet simple and consistent toolset for manipulating JavaScript dates in a browser & Node.js

👉 Documentation

👉 Blog


It's like Lodash for dates

  • It has 200+ functions for all occasions.
  • Modular: Pick what you need. Works with webpack, Browserify, or Rollup and also supports tree-shaking.
  • Native dates: Uses existing native type. It doesn't extend core objects for safety's sake.
  • Immutable & Pure: Built using pure functions and always returns a new date instance.
  • TypeScript: The library is 100% TypeScript with brand-new handcrafted types.
  • I18n: Dozens of locales. Include only what you need.
  • and many more benefits
import { compareAsc, format } from "date-fns";

format(new Date(2014, 1, 11), "yyyy-MM-dd");
//=> '2014-02-11'

const dates = [
  new Date(1995, 6, 2),
  new Date(1987, 1, 11),
  new Date(1989, 6, 10),
];
dates.sort(compareAsc);
//=> [
//   Wed Feb 11 1987 00:00:00,
//   Mon Jul 10 1989 00:00:00,
//   Sun Jul 02 1995 00:00:00
// ]

The library is available as an npm package. To install the package run:

npm install date-fns --save

Docs

See date-fns.org for more details, API, and other docs.


License

MIT © Sasha Koss