最近の日時フォーマット処理はどうなっているのか調べてみた(JavaScript編)

日時フォーマット処理は進化しているのか?

このタイトル、どこかで見たことが…?(もしかしたら見たことある人もいるかもしれない)

以前、同名のタイトルでJava編を書きまして、今回はJavaScript編です。
Java編はこちら。

 

私は日頃結構JavaScriptにも触れるので、今回はJavaScriptの日時フォーマット処理についてやってみたいと思います。
変換後のフォーマットは、Java編と同じく「yyyy/MM/dd HH:mm」にします。

年、月、日、時、分をそれぞれ取得して組み合わせる

どうでもいいですが、私はこれを勝手に「愚直パターン」と呼んでいます。

現在日時から、年月日時分をそれぞれ別々に取得して、最後に組み合わせて表示しています。
月日時分の取得結果に対して 「’0′ + 」とか「.slice(-2)」とかしているのは、一桁の場合に0埋めするためですね。
0埋めしなくてもよいならもう少しコードはスッキリするのかと思うと、0埋めって大変なのねぇ…という気持ちになってきます。

ちなみにこれはES(ECMAScript)5の書き方で、ちょっと古めの書き方です。(ES5が2009年、ES5.1が2011年リリース)
最新のES(ES14、2023年)で書くと以下のようになります。

なんかちょっとだけかっこよくなりましたね。(?)
古い書き方との違いは、0埋めをしてくれるpadStartメソッドと、テンプレートリテラル(バッククォートを使用した文字列)が使えるようになったところでしょうか。
padStartメソッドはES8(2017年)に、テンプレートリテラルはES6(2015年)に誕生したものです。

ちょっとかっこよく書けるようになったものの、まあ処理の長さ的には大して変わりません。
古き良きというか、長く受け継がれてきた基本の書き方、って感じがします。

日本語ロケールと書式を指定して日時を文字列変換する

toLocaleStringメソッドを使った書き方です。
このメソッド自体は昔から(ES5.1くらいから)あったようなので、そこまで新しい書き方というわけでもなさそうです。
が、年月日時分をそれぞれ取得して組み合わせるさっきの方法よりすごくスマートな感じがする!
私が個人的にこちらの方が好き、というのが大きいかもしれません。

ちなみにオプション(options)なしでtoLocaleStringを実行すると、以下のようになります。

日本語ロケールだと、0埋めしないんですね。

他言語ロケールを指定して日時を文字列変換する

「JavaScriptってどう頑張っても一行で書くのは無理なんだなぁ」と思い始めた矢先、ここに来て最短コードが…!
定数todayを切らなければ1行で書けます。(強気)

しかし、他言語ロケールを指定するとは。
日本だから日本語ロケール指定しなきゃいけないかと思ってましたが、うまい使い方があるものですね。
上記コードでは、ロケールにスウェーデン(sv-SE)を指定しています。

ちなみにシンプルに(replaceとかせずに)toLocaleStringを実行すると、以下のようになります。

replace以降の処理でやっているのは、「-を/に置き換えて、後ろ3文字を削除する」ですね。
これで私の求めるフォーマットになるわけです。なるほど。

余談ですが、リトアニア(lt-LT)でも同じ結果が得られます。

外部ライブラリを使う

今回は、メジャーなライブラリということで以下の2つを見てみます。

Day.jsを調べてみると、大抵セットのようにMoment.jsという名前も出てきますが、Moment.jsは開発が終了したので、新規開発では採用しないほうがよさそうです。
Moment.jsに慣れている人は、同じAPI体系を持つということで、後継としてDay.jsを選択するとよいかもしれません。

Day.jsを使う

おー!シンプルだしめちゃくちゃわかりやすい!
formatでフォーマットを指定したら一発です。

ちなみに、細かいですが、Day.jsでは「yyyy/MM/dd」ではなく「YYYY/MM/DD」のようです。
JavaScriptの世界において、厳密には小文字と大文字で異なる意味を持ちますが、Day.jsにおいては大文字しか受け入れてもらえないようです。
まあそういうルールなのでしょう。

date-fnsを使う

おー!こちらもわかりやすい!
使い方は大体Day.jsと同じに見えますが、Day.jsはオブジェクト指向、date-fnsは関数型、という違いがあります。

結局どの書き方がよいのか!?

外部ライブラリは他にも色々種類があるのですが、一般的な実装は今回ご紹介したものがメインどころかなと思います。

さて、Java編でも処理速度比較をしましたが、一応JavaScript編でもやりたいと思います…!
ただ、自力で処理速度を計測したところ、環境の影響なのか実行の度にばらつきが激しく安定しなかったので、パフォーマンス計測サイト JSBench.Me で計測してみました。
コードの内容的には計測サイト使ってやるほどのものでもないのですが、私が手動で計測するよりかなり信ぴょう性があるので、今回はツールを頼らせていただこうと思います。

文字が小さくてわかりにくいかもしれませんが、なんと、一番古い書き方が一番速いという結果に!
上記結果は速い順にソートしています。

改めて結果を記載すると以下のようになります。(速い順)

  1. 年月日時分組み合わせ(ES5バージョン)
  2. 年月日時分組み合わせ(ES2023バージョン)
  3. toLocaleString(スウェーデン)
  4. toLocaleString(リトアニア)
  5. date-fns
  6. Day.js
  7. toLocaleString(日本)

…とはいえ、1回あたりの実行時間だけ見るとほぼ差はないに等しいです。(計測しておいて何言ってんだという感じですが)
保守性や可読性という点では、外部ライブラリが圧倒的優位かなと思います。
スウェーデンやリトアニアのやり方は、目からウロコ!な感じはありましたが、イレギュラーなやり方であることは確かなので、個人的にはあまりおすすめしません。

Day.js vs date-fns

ちなみに、外部ライブラリならDay.jsとdate-fns、どっちがいいのよ?と思う方もいるかも!と思い、ちょっとトレンドを調べてみました。

Googleトレンドだとこんな感じです。

世界地図で見ても全体的に赤味が多く、世界的にはdate-fnsに興味がある人が多いようです。
国別で見ると、Day.jsに興味があるのはアジア諸国がメイン、という感じでした。
Day.jsがアジア諸国で人気な理由はよくわからず…関係あるかはわかりませんが、コントリビューターの中でも中国の方が活発に開発しているようです。

npm trendsだとこちら。

そんなに差がないようにも見えますが、1目盛りが500万なので、ここ3ヶ月間くらいは500~1000万くらいの差でdate-fnsの方が多くダウンロードされているようです。

ここまで見ると、トレンドとしてはdate-fnsの方が優位なのかな?という気もします。
が、使い勝手などは好みの部分もありますので、先に書いたように、もともとMoment.jsを使っていた人にとってはDay.jsのほうが使いやすいかもしれません。
オブジェクト指向好きな人はDay.js、関数型好きな人はdate-fns、とか。

また、実際に開発プロジェクトで外部ライブラリを採用する際には、そのライブラリが活発に開発されていることも大事な要素になると思います。
要件や好みに合わせて、ぜひ良い選択をしてください!

お問い合わせ先

執筆者プロフィール

Yamazaki Naoko
Yamazaki Naokotdi デジタルイノベーション技術部
社内の開発プロジェクトの技術支援や、新技術の検証に従事しています。主にアプリケーション開発系支援担当で、Java&サーバサイドが得意です。最近は、サーバーレスonAWSを推進しています。

関連記事