日付ライブラリの強み、弱み、開発背景を調査した

2024/03/03に公開

はじめに

以前日付ライブラリを比較したがもう少し深掘りしようと思う。
この記事では各日付ライブラリができた背景、強み、弱みに焦点を当ててまとめていきたいと思う。
https://zenn.dev/rlab/articles/d9ead34cfb0ede

本記事は vue を使用する
調査するライブラリは以下の 4 つ

dayjs

開発された背景

moment.js のファイルサイズが大きいことと、パフォーマンスの問題を解決するために開発された。
実際に サイズは 2kb かつ高パフォーマンスで moment.js の代替品であることが記載されている。
https://day.js.org/

強み

Day.js の強みは、軽量性(2KB)と Moment.js との互換性。
学習コストの少なさ。
プラグインで機能を拡張できる。

弱み

Day.js は標準でタイムゾーンをサポートしていないため、グローバルなタイムゾーンを扱う場合、Luxon や Moment Timezone のようなライブラリが必要になる。
また、特定の日付フォーマットの解析や、複雑な日付計算が必要な場合、Date-fns や Moment.js が提供する機能が必要になる場合がある。

以下、プラグインを読み込むサンプルコード

<script setup>
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";

// プラグインを使用するためにDay.jsに登録
dayjs.extend(utc);
dayjs.extend(timezone);

// タイムゾーンを指定して日付を表示
console.log(dayjs().tz("Asia/Tokyo").format());

const date = dayjs().format("YYYY年MM月DD日");
</script>

<template>
  <div>{{ date }}</div>
</template>

date-fns

開発された背景

モジュール性とパフォーマンスに重点を置いて開発された
各機能を個別の関数として提供し、必要なものだけをインポートして使用できるようにすることで、最終的なバンドルサイズを大幅に削減した。(tree-shaking の標準搭載)
これにより、特にバンドルサイズに敏感なウェブアプリケーションに適している
https://github.com/date-fns/date-fns

強み

ライブラリの中から必要な部分だけを使うことができるため軽量である。
日付を扱う既存の型を拡張せず、純粋な関数として日付を操作する。(不変性)
以下サンプルでは、originalDate は変更されず、addDays 関数によって新しい日付 newDate が生成されている。
これは date-fns が不変性を保持する設計になっているため。

<script setup>
import { addDays } from "date-fns";

const originalDate = new Date(2024, 3, 3); // 2024年3月3日
const newDate = addDays(originalDate, 5); // 5日後

console.log(originalDate); // 変更されていない元の日付
console.log(newDate); // 新しい日付インスタンス
</script>

<template>
  <div>{{ date }}</div>
</template>

setDate や setMonth のようなメソッドは、元の Date オブジェクトを変更する.

<template>
  <div>
    <p>index page</p>
  </div>
</template>

<script setup>
let today = new Date(); // 今日の日付
console.log("元の日付:", today);

// 日付を設定
today.setDate(15);
console.log("日を変更後:", today);

// 月を設定(月は0から始まるので、0は1月を意味します)
today.setMonth(0);
console.log("月を変更後:", today);
</script>

実行結果

弱み

多くの関数とオプションがあるため、使いこなすまでに時間がかかることがある。
タイムゾーンを直接扱う機能が限られている。


luxon

開発された背景

Moment.js チームによって開発され、Moment.js の代替として、よりモダンな API と改善された機能を提供することを目的として開発された。
moment を引き継ぎつつ、moment の弱点を補った感じ。
https://moment.github.io/luxon/#/why

強み

タイムゾーンのサポートと国際化機能に優れている点。
また、不変性を持つ API で日付と時刻を扱うことができる。

以下、タイムゾーンのサンプル

<script setup>
import { DateTime } from "luxon";

// 現在の日付と時刻を取得し、ローカルタイムゾーンで表示
const now = DateTime.now();
console.log(now.toString());

// タイムゾーンを指定して日付を表示
const tokyoTime = now.setZone("Asia/Tokyo");
console.log(tokyoTime.toString());
</script>

<template>
  <div>{{ date }}</div>
</template>

弱み

ファイルサイズが大きい。
学習コストがかかる。


@formkit/tempo

開発された背景

moment.js、day.js、date-fns などにインスパイアされ、Tempo は可能な限り小さく、使いやすくなるように 1 から作られた。
他のライブラリと違い、Date オブジェクトを直接操作することで軽量化されている。
https://github.com/formkit/tempo

強み

軽量である。
ドキュメントがかっこいい。
helper が直感的で使いやすい。
以下、時間の前後を比較する helper のサンプル

<script setup>
import { isBefore } from "@formkit/tempo";

// true
const hoge = isBefore("2013-03-15", "2013-03-16");

// false
const fuga = isBefore("2013-03-17", "2013-03-16");
</script>

<template>
  <div>{{ hoge }},{{ fuga }}</div>
</template>

弱み

新しすぎて情報がほとんどない(2024/03/03 現在)


まとめ

moment.js が元になりつつ、その弱点を補うために日付ライブラリが進化してきたことがわかった。
@formkit/tempo がこれからどう使われていくか、他のライブラリを押さえてメジャーになっていくのか楽しみである。

Discussion