dayjs vs js-joda vs luxon vs moment
現代のフロントエンド開発における日時処理ライブラリの選定
dayjsjs-jodaluxonmoment類似パッケージ:

現代のフロントエンド開発における日時処理ライブラリの選定

moment、dayjs、luxon、js-joda は、JavaScript 環境で日時の解析、操作、フォーマットを行うための主要なライブラリです。moment は長年デファクトスタンダードでしたが、現在は保守モードに入っており、新規プロジェクトでの使用は推奨されません。dayjs は moment と互換性のある API を持ちつつ軽量で、luxon は moment の開発者によって作られた不変型ライブラリでネイティブの Intl API を利用します。js-joda は Java の日時 API のポートであり、厳格な不変性を求めるドメインロジックに適しています。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
dayjs048,666682 kB1,3501ヶ月前MIT
js-joda01,663-117年前BSD-3-Clause
luxon016,4614.59 MB1921年前MIT
moment0-4.5 MB-13日前MIT

日時処理ライブラリ完全比較:Moment, Day.js, Luxon, js-joda

JavaScript で日時を扱うことは、一見簡単そうで実は複雑な課題です。タイムゾーン、うるう年、ローカライゼーションなど、考慮すべき点が多くあります。moment、dayjs、luxon、js-joda は、この問題を解決するための主要な選択肢ですが、それぞれ設計思想とトレードオフが異なります。エンジニアリングの観点から、これらのライブラリを深く比較します。

🚨 保守状況と将来性

ライブラリを選定する際、まず確認すべきはメンテナンス状況です。長期にわたるプロジェクトでは、ライブラリが将来もサポートされ続けるかが重要です。

moment は現在、保守モードに入っています。

  • 新たな機能は追加されません。
  • バグ修正のみが行われる状態です。
  • 新規プロジェクトでの使用は公式に非推奨です。
// moment: 保守モード入り
// 新規プロジェクトでは避けるべき
const m = moment(); 

dayjs はアクティブに開発が続いています。

  • 軽量さを維持しながらプラグインで拡張します。
  • コミュニティによる貢献が活発です。
// dayjs: アクティブ開発中
import dayjs from 'dayjs';
const d = dayjs();

luxon も安定したメンテナンスが続いています。

  • moment の開発者によって作成されました。
  • 標準仕様への準拠を重視しています。
// luxon: 安定メンテナンス
import { DateTime } from 'luxon';
const d = DateTime.now();

js-joda は堅牢性を重視して開発されています。

  • 変更よりも安定性を優先します。
  • 特定のドメイン要件に向いています。
// js-joda: 堅牢性重視
import { LocalDateTime } from '@js-joda/core';
const d = LocalDateTime.now();

🔄 設計思想:可変 vs 不変

日時オブジェクトが操作後に自身を書き換えるか(可変)、新しいオブジェクトを返すか(不変)は、バグの発生率に直結します。

moment は可変型です。

  • 操作すると元のオブジェクトが書き換わります。
  • 参照渡しによる予期せぬ副作用が起きやすいです。
// moment: 可変型
const a = moment();
const b = a; // 参照コピー
a.add(1, 'day');
console.log(b.format()); // a と b が同じ日時になる

dayjs も基本的に可変型です。

  • moment との互換性を重視した設計です。
  • 不変化プラグインを利用することも可能です。
// dayjs: 可変型(デフォルト)
const a = dayjs();
const b = a; // 参照コピー
const c = a.add(1, 'day'); // 新しいインスタンスを返す場合もあるが注意が必要

luxon は不変型です。

  • 操作するたびに新しいインスタンスを返します。
  • 状態管理が予測しやすく、バグが減ります。
// luxon: 不変型
const a = DateTime.now();
const b = a; // 参照コピーだが中身は変わらない
const c = a.plus({ days: 1 }); // a は変更されない
console.log(a.equals(c)); // false

js-joda は厳格な不変型です。

  • Java の日時 API の考え方を引き継いでいます。
  • 副作用を完全に排除したい場合に適しています。
// js-joda: 厳格な不変型
const a = LocalDateTime.now();
const b = a; 
const c = a.plusDays(1); // a は変更されない

📅 主要機能の実装比較

実際のコードで、どのように日時を扱うか比較します。 parsing(解析)、manipulation(操作)、formatting(フォーマット)の 3 点を見ます。

日時の解析(Parsing)

moment は文字列を柔軟に解析します。

  • 形式を指定しなくても推測しようとします。
  • 予期せぬ解析結果になるリスクがあります。
// moment
const m = moment('2023-10-01');

dayjs も柔軟な解析を行います。

  • moment とほぼ同じ挙動です。
  • 厳密な形式指定はプラグインで強化します。
// dayjs
const d = dayjs('2023-10-01');

luxon は形式を明確に指定します。

  • ISO 形式などがデフォルトでサポートされています。
  • 曖昧さを排除した設計です。
// luxon
const l = DateTime.fromISO('2023-10-01');

js-joda は厳密な形式を要求します。

  • 明確なフォーマット指定が推奨されます。
  • 実行時エラーで不正な形式を防ぎます。
// js-joda
const j = LocalDateTime.parse('2023-10-01T00:00');

日時の操作(Manipulation)

moment はチェーン操作で加算します。

  • 可読性は高いですが、副作用に注意が必要です。
// moment
const m = moment().add(1, 'day').subtract(2, 'hour');

dayjs もチェーン操作をサポートします。

  • moment と同じ文法で書けます。
// dayjs
const d = dayjs().add(1, 'day').subtract(2, 'hour');

luxon はオブジェクトで単位を指定します。

  • typo を防ぎやすく、明確です。
// luxon
const l = DateTime.now().plus({ days: 1 }).minus({ hours: 2 });

js-joda はメソッド名で単位を区別します。

  • 非常に明確ですが、コードが長くなりがちです。
// js-joda
const j = LocalDateTime.now().plusDays(1).minusHours(2);

日時のフォーマット(Formatting)

moment はトークン形式を使います。

  • YYYY-MM-DD などの形式は一般的です。
  • 記憶しやすいですが、標準仕様ではありません。
// moment
const str = moment().format('YYYY-MM-DD');

dayjs もトークン形式を使います。

  • moment と互換性があります。
// dayjs
const str = dayjs().format('YYYY-MM-DD');

luxon は Unicode 標準の形式を使います。

  • yyyy-MM-dd など、小文字区別があります。
  • 標準仕様に準拠しています。
// luxon
const str = DateTime.now().toFormat('yyyy-MM-dd');

js-joda はフォーマッタオブジェクトを使います。

  • 最も厳格で、ミスが発生しにくいです。
// js-joda
const formatter = DateTimeFormatter.ofPattern('yyyy-MM-dd');
const str = LocalDateTime.now().format(formatter);

🌍 タイムゾーン処理

グローバルなアプリでは、タイムゾーン処理が不可欠です。ここがライブラリ間の大きな違いになります。

moment はプラグインが必要です。

  • moment-timezone を別途インストールします。
  • データファイルが大きくなりがちです。
// moment
import 'moment-timezone';
moment.tz('2023-10-01', 'America/New_York');

dayjs もプラグインが必要です。

  • timezone プラグインを読み込みます。
  • 必要なタイムゾーンデータだけを読み込めます。
// dayjs
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.tz('2023-10-01', 'America/New_York');

luxon は標準機能でサポートします。

  • 追加プラグインは不要です。
  • Intl API を内部で利用します。
// luxon
DateTime.fromISO('2023-10-01', { zone: 'America/New_York' });

js-joda は別途パッケージが必要です。

  • @js-joda/timezone を使用します。
  • 厳密なタイムゾーン計算が可能です。
// js-joda
import { ZonedDateTime, ZoneId } from '@js-joda/core';
import '@js-joda/timezone';
ZonedDateTime.parse('2023-10-01T00:00-04:00[America/New_York]');

📦 依存関係と環境

ブラウザのサポート範囲も選定基準になります。

moment は依存関係がありません。

  • 古いブラウザでも動作します。
  • 自分でポリフィルを用意する必要はありません。

dayjs も依存関係がありません。

  • 古いブラウザとの親和性が高いです。
  • 軽量なため、モバイル環境でも有利です。

luxon は Intl API に依存します。

  • 古いブラウザ(IE など)ではポリフィルが必要です。
  • 最新環境ではネイティブ処理により高速です。

js-joda は依存関係が少ないです。

  • 環境を選ばず動作します。
  • Node.js バックエンドとの親和性が高いです。

📊 _summary 表

特徴momentdayjsluxonjs-joda
保守状況🛑 保守モード✅ アクティブ✅ 安定✅ 安定
変更性質🔴 可変🔴 可変🟢 不変🟢 不変
サイズ感🐘 大きい🐦 軽量🐕 中程度🐕 中程度
タイムゾーン🔌 プラグイン🔌 プラグイン✅ 標準機能🔌 別パッケージ
API 风格チェーンチェーンオブジェクトメソッド名
推奨度❌ 非推奨✅ 高い✅ 高い⚠️ 特殊用途

💡 結論と推奨

moment は、もはや新規プロジェクトの選択肢ではありません。保守モード入りしているため、技術的負債になります。既存プロジェクトであれば、移行計画を立てるべきです。

dayjs は、moment のような書き心地を維持しつつ、軽量さを求めている場合に最適です。フロントエンドの UI 表示や、シンプルな日時操作に向いています。プラグイン構成により、必要な機能だけを含められるのも魅力です。

luxon は、不変型による安全性と、標準仕様への準拠を重視する場合に選べきです。状態管理の複雑さを減らしたい大規模アプリや、タイムゾーン処理を標準機能で済ませたい場合に有利です。ただし、古いブラウザサポートには注意が必要です。

js-joda は、日時計算の正確性がビジネスロジックの核心となる場合に適しています。金融システムやスケジューリングシステムなど、バグが許されない領域での利用が考えられます。フロントエンドの UI 処理としてはオーバーワークになる可能性があります。

最終的なアドバイス:新規プロジェクトでは dayjs または luxon を選定し、moment は避けてください。不変性を求めるなら luxon、軽量さと互換性を求めるなら dayjs が良いでしょう。

選び方: dayjs vs js-joda vs luxon vs moment

  • dayjs:

    dayjs は、moment のような直感的な API を求めつつ、バンドルサイズを小さく抑えたい場合に最適です。プラグイン機構により必要な機能だけを追加できるため、軽量さを維持しながら拡張できます。既存の moment プロジェクトからの移行コストが最も低いのも特徴です。ただし、デフォルトでは可変型であるため、副作用に注意する必要があります。

  • js-joda:

    js-joda は、厳格な不変性と型安全性が求められるビジネスロジックやバックエンド寄りの処理に適しています。Java の ThreeTen プロジェクトに基づいており、日時計算の信頼性が非常に高いです。ただし、API が他のライブラリとは大きく異なり、学習コストが高いため、フロントエンドの UI 処理よりもドメイン層での利用を検討すべきです。

  • luxon:

    luxon は、不変型 API を採用しており、予期せぬ状態変化を防ぎたいアーキテクチャに適しています。ネイティブの Intl API を利用するため、最新ブラウザでは軽量に動作しますが、古いブラウザではポリフィルが必要です。moment の開発者による後継ライブラリであり、バランスの取れた選択と言えます。

  • moment:

    moment は、すでに保守モードに入っているため、新規プロジェクトでの使用は避けるべきです。既存のレガシープロジェクトを維持する場合や、膨大な既存コードベースを抱えており移行が現実的に困難な場合にのみ検討します。将来的なメンテナンスコストを考慮すると、代替ライブラリへの移行を計画すべきです。

dayjs のREADME

English | 简体中文 | 日本語 | Português Brasileiro | 한국어 | Español (España) | Русский | Türkçe | සිංහල | עברית

Day.js

Fast 2kB alternative to Moment.js with the same modern API

Gzip Size NPM Version Build Status Codecov License
Sauce Test Status

Day.js is a minimalist JavaScript library that parses, validates, manipulates, and displays dates and times for modern browsers with a largely Moment.js-compatible API. If you use Moment.js, you already know how to use Day.js.

dayjs().startOf('month').add(1, 'day').set('year', 2018).format('YYYY-MM-DD HH:mm:ss');
  • 🕒 Familiar Moment.js API & patterns
  • 💪 Immutable
  • 🔥 Chainable
  • 🌐 I18n support
  • 📦 2kb mini library
  • 👫 All browsers supported

Getting Started

Documentation

You can find more details, API, and other docs on day.js.org website.

Installation

npm install dayjs --save

📚Installation Guide

API

It's easy to use Day.js APIs to parse, validate, manipulate, and display dates and times.

dayjs('2018-08-08') // parse

dayjs().format('{YYYY} MM-DDTHH:mm:ss SSS [Z] A') // display

dayjs().set('month', 3).month() // get & set

dayjs().add(1, 'year') // manipulate

dayjs().isBefore(dayjs()) // query

📚API Reference

I18n

Day.js has great support for internationalization.

But none of them will be included in your build unless you use them.

import 'dayjs/locale/es' // load on demand

dayjs.locale('es') // use Spanish locale globally

dayjs('2018-05-05').locale('zh-cn').format() // use Chinese Simplified locale in a specific instance

📚Internationalization

Plugin

A plugin is an independent module that can be added to Day.js to extend functionality or add new features.

import advancedFormat from 'dayjs/plugin/advancedFormat' // load on demand

dayjs.extend(advancedFormat) // use plugin

dayjs().format('Q Do k kk X x') // more available formats

📚Plugin List

Downloads

Day.js Chart

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website.

[Become a sponsor via Github] [Become a sponsor via OpenCollective]

                                             Instagram Story Viewer          Sayfone Cheap international calls                   BestKru                   Route Optimizer and Route Planner Software                                             

Contributors

This project exists thanks to all the people who contribute.

Please give us a 💖 star 💖 to support us. Thank you.

And thank you to all our backers! 🙏

License

Day.js is licensed under a MIT License.