Moment.js と date-fns でローカライズされた日付文字列への変換方法を調査してみた
こんにちは。最近、 PHP Conference Japan 2023 のトーク募集に申し込んだ k-so16 です。初めて proposal を提出したので、採択されるかなという不安と、採択されたらいいなという期待の半々の気持ちで日々過ごしています (笑)
とあるプロジェクトで、日付の操作に Moment.js を利用し、日本語の日付文字列を出力するために date-fns を利用しているコードを見かけました。わざわざ date-fns を使っているのは、 Moment.js だけでは日本語の日付文字列に変換できないのだろうかと疑問に思いました。
それぞれのライブラリーを調べてみると、どちらも日本語の日付文字列に変換できることがわかりました。残念ながら、なぜ使い分けているかはわかりませんでした。
本記事では、 Moment.js と date-fns でローカライズされた日付文字列に変換する方法 を紹介します。
本記事で想定する読者層は以下の通りです。
- Moment.js についての基礎的な使い方を知っている
- date-fns についての基礎的な使い方を知っている
Moment.js と date-fns の違い
Moment.js と date-fns は、どちらも 日付や時間を扱うライブラリー です。日付の加算や 2 つの日付の比較など、さまざまな演算を簡単に記述できます。
2 つのライブラリーできることは大きく変わりません。大きな違いとして、返される日付オブジェクトが違うということが挙げられます。
- Moment.js は基本的に
Moment
オブジェクトを返す - date-fns は基本的に
Date
オブジェクトを返す
Moment.js は独自の Moment
オブジェクトを返します。一方、 date-fns は標準の Date
オブジェクトを返します。
Moment.js は Moment
オブジェクトを基本的に返すため、複数の日付の操作を、 メソッドチェイン で書くことができます。ただし、 Date
を受け取るインタフェースに Moment.js で操作した日付データを渡す際には、その都度 .toDate()
で型変換する必要があります。
一方、 date-fns の場合は Date
オブジェクトを返すため、 Moment.js のように複数の操作をメソッドチェインで書くことはできません。かわりに、 date-fns で操作した日付データは、 Date
を受け取るインタフェースへ 型変換をすることなく 、直接渡すことができます。
ローカライズされた日付文字列への変換方法
Moment.js と date-fns では、ローカライズの方法や、日付文字列への変換フォーマットの違いはあれど、基本的に同じ日付文字列を出力できます。
以下のセクションでは、ロケールを日本に設定して、 2023年7月25日 (火)
のような、年月日と日本語の曜日を含む日付文字列に変換する場合を考えてみます。
なお、コード例は Node.js 上での動作を想定し、 CommonJS の記法で記述しています。 ECMAScript の記法の場合も、 require
の行を import
に変える ことで、同様の動作になるはずです。
Moment.js の場合
Moment.js の場合、 locale()
というメソッドを利用することで、扱う日付のロケールを設定できます。 ロケールを設定したあと、 format()
で日付のフォーマット文字列を生成する と、ローカライズされた日付文字列に変換できます。
Moment.js では、日本語にローカライズした状態でフォーマット文字列に LL
を指定すると、 2023年7月25日
のように、年月日の日付文字列に変換します。また、 ddd
を指定すると、 火
のように、短い曜日表記に変換されます。
Moment.js でローカライズされた日付文字列に変換するコード例は以下の通りです。
const moment = require('moment');
const date = moment().locale('ja').format('LL (ddd)');
console.log(date); // 出力例: 2023年7月25日 (火)
date-fns の場合
date-fns の場合は、 date-fns/locale
から、 対象のロケールのオブジェクトを読み込みます。 日付文字列をローカライズするには、 date-fns の format()
メソッドの第 3 引数に、 locale
プロパティをもつオブジェクト を指定します。
date-fns では、日本語にローカライズした状態でフォーマット文字列に PPP
を指定すると、 2023年7月25日
のように、年月日の日付文字列に変換します。また、 E
を指定すると、 火
のように、短い曜日表記に変換されます。
date-fns でローカライズされた日付文字列に変換するコード例は以下の通りです。
const { format } = require('date-fns');
const { ja } = require('date-fns/locale');
const date = format(new Date(), 'PPP (E)', { locale: ja });
console.log(date); // 出力例: 2023年7月25日 (火)
Moment.js と date-fns のフォーマットの比較
日付文字列へ変換する際に、 Moment.js と date-fns でフォーマットの指定方法を比較してみます。年月日と曜日、および時分秒のそれぞれについて、よく使われそうなフォーマットを比較してみます。
以下の表は Moment.js と date-fns の日付フォーマットの一部です。
項目 | Moment.js のフォーマット | date-fns のフォーマット | デフォルトの表示例 | 日本語の表示例 |
---|---|---|---|---|
年 | YYYY |
yyyy |
2023 | 2023 |
月 | M |
M |
7 | 7 |
月 (2 桁表記) | MM |
MM |
07 | 07 |
月 (ローカライズ表記 (省略形)) | MMM |
MMM |
Jul | 7月 |
月 (ローカライズ表記) | MMMM |
MMMM |
July | 7月 |
日 | D |
d |
1 | 1 |
日 (2 桁表記) | DD |
dd |
01 | 01 |
日 (ローカライズ表記) | Do |
do |
1st | 1日 |
曜日 (ローカライズ表記 (省略形)) | ddd |
EEE |
Sat | 土 |
曜日 (ローカライズ表記) | dddd |
EEEE |
Saturday | 土曜日 |
時間 (12 時間表記) | h |
h |
1 | 1 |
時間 (12 時間表記 (2 桁)) | hh |
hh |
01 | 01 |
時間 (24 時間表記) | H |
H |
13 | 13 |
時間 (24 時間表記 (2 桁)) | HH |
HH |
13 | 13 |
分 (2 桁表記) | mm |
mm |
01 | 01 |
秒 (2 桁表記) | ss |
ss |
02 | 02 |
年月日 | L |
P |
07/01/2023 | 2023/07/01 |
年月日 (ローカライズ表記 (省略形)) | ll |
PP |
Jul 1, 2023 | ※1 |
年月日 (ローカライズ表記) | LL |
PPP |
※2 | 2023年7月1日 |
時分 | LT |
p |
12:01 PM | 12:01 |
時分秒 | LTS |
pp |
12:01:25 PM | 12:01:25 |
基本的に同じ表記に変換できますが、 残念ながら フォーマットは共通ではありません。 時間や分、秒のように、同じフォーマットのものもありますが、 ほとんどの場合はフォーマットが異なります。
また、上記の表の※1, ※2 は、 Moment.js と date-fns で変換結果が若干異なります。以下の表に、それぞれの変換結果の例を示します。
項目 | Moment.js での表示例 | date-fns での表示例 |
---|---|---|
※1 | 2023年7月1日 | 2023/07/01 |
※2 | July 1, 2023 | July 1st, 2023 |
※1 では、Moment.js の場合、日本語にローカライズした年月日へ変換する場合は LL
も ll
も同じ結果になります。一方で、 date-fns の場合は PP
と PPP
で結果が異なります。
また、※2 では、 date-fns の場合は日付の後ろに st
のような接尾辞がつきますが、 Moment.js の場合はつきません。
混乱を避けるためにも、よほどの事情がない限りは Moment.js か date-fns の どちらか一方のみを利用 したほうが良さそうですね。
ちなみに、 Moment.js は公式ドキュメントで、新たな機能追加などの大きな変更は行わず、保守のみサポートすると述べています。そのため、新しくプロジェクトを立ち上げる際には、 date-fns や Luxon などの ほかのライブラリーを利用することを推奨 しています。
本記事を執筆する上で、以下の記事を参考にしました。
まとめ
本記事のまとめは以下の通りです。
- Moment.js と date-fns でローカライズされた日付文字列に変換する方法を紹介
- Moment.js と date-fns の代表的な変換フォーマットを紹介
以上、 k-so16 でした。ぜひ、それぞれのライブラリーでどのようなフォーマットに変換できるか試してみてくださいね (笑)