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

Pocket

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

私はどちらかというとアプリ畑の人間なのですが、どんなアプリでもいつもよく見るしよく使うのが日時のフォーマット変換処理です。
特に画面があるようなアプリ(Webとか)だと、日時型では「yyyy-MM-dd HH:mm:ss」でデータ保持しているのに、画面では文字列の「yyyy/MM/dd」や「HH:mm」(ss不要など)などで表示したいの、あるあるですよね。

そんな、いにしえから存在するフォーマット変換処理ですが、最近どうなの?進化してるの?何か新しい書き方でも生まれたかな?と勝手に気になり、調べて&試してみました。

言語は私の独断で、私が馴染みのあるJavaを対象にします。
変換後のフォーマットは、これまた私の独断で、「yyyy/MM/dd HH:mm」にします。(よく使う気がするから)

java.textパッケージを使う

java.text.SimpleDateFormat

誰もがここから始める(と思われる)SimpleDateFormat…!
昔からあるし、一行でバシーンと変換できるので、コード的にはかなりスッキリ書けます。

java.text.DateFormat

一見よさそうに見えますが、これだと厳密には私の要件を満たしていません。
10時以降なら問題ないですが、9時以前なら「2025/01/28 9:00」ように出力されてしまいます。(本当は「09:00」と表示してほしい)

DateFormatの場合、今回はgetInstanceメソッドでDateFormatオブジェクトを生成していますが、他にもgetXXInstanceメソッド(XXにはいくつか種類あり)が用意されているので、どれを使うかによってフォーマットが変わるようです。
ただ、用意されているインスタンスでは私がほしいフォーマットは実現できなさそうでした。無念。

java.timeパッケージを使う

java.time.DateTimeFormatter

java.textパッケージとの違いは、扱う日時オブジェクトがjava.util.Dateではなくjava.time.LocalDateTimeになっている点ですね。

ちなみに、以下のようにZonedDateTimeに置き換えることもできます。

ちなみにちなみに、Instantを使っても以下のように記述できます。

見てわかるかと思いますが、Instantと言いつつ結局はZonedDateTimeに変換してるんですけどね…。

LocalDateTimeとZonedDateTimeとInstantの違いは、話すときっと長くなるので割愛します。
また、機能によってどれを使うのが最適かも変わってくると思うので、「絶対これ!」なおすすめも特にありません。
今回の私みたいな使い方だとLocalDateTimeで十分かな~という気もしますが、時差情報を持っておきたい場合はZonedDateTimeの方がよさそうです。

外部ライブラリを使う

org.apache.commons.lang3.time.FastDateFormat

外部ライブラリで何かないんか?と探したところ、ヒットしたのがこちらのAPIです。
apache.commons.lang3ライブラリを導入すると使えます。
もうここまでくると、Javaの日時フォーマット処理って全部大体同じように書けるんだなという気持ちになります。

FastDateFormatはLocalDateTimeではなくDateを扱うAPIになっています。

まとめ

フォーマットによっては他にも色々な実装方法があるかと思いますが、一旦私がやりたいフォーマットとしてはこれまで紹介した実装方法が一般的なのかなぁ~という印象です。
ただこれで終わるのも面白くないので(?)、処理速度を計測してみました。
また、スレッドセーフかどうかも併せて以下にまとめてみます。

  処理速度 スレッドセーフ?
java.text.SimpleDateFormat 71 ミリ秒 No
java.text.DateFormat 1 ミリ秒 No
java.time.DateTimeFormatter(LocalDateTime) 2 ミリ秒 Yes
java.time.DateTimeFormatter(ZonedDateTime) 1 ミリ秒 Yes
java.time.DateTimeFormatter(Instant) 0 ミリ秒 Yes
org.apache.commons.lang3.time.FastDateFormat 24 ミリ秒 Yes

ミリ秒単位で計測したので0ミリ秒を叩き出してしまっていますが、そこは優しい目で見てください。
こう並べてみると、一番速いのはDateTimeFormatterのInstant版ということになります。
同じDateTimeFormatterでもLocalDateTime、ZonedDateTime、Instantで差が出ているのは、日時オブジェクトの生成にかかる時間の違い…?なのかな??

そしてWebアプリを開発するときに絶対意識しておきたいスレッドセーフ。
SimpleDateFormatとDateFormatはスレッドセーフではありません
FastDateFormatは「SimpleDateFormatのスレッドセーフ版」と自ら言っている(APIドキュメントの冒頭に書いています)ので、SimpleDateFormatの代替としてFastDateFormatを使うとよいのかもしれません。

また、Java界ではjava.util.Dateは古いAPI、java.time.LocalDateTimeは新しいAPIなので、もし特段Dateを選択する理由がないのなら、積極的にLocalDateTimeやZonedDateTimeを使っていった方がよいのかなと思います。
要するに、java.timeパッケージが新しいAPIシリーズってことですね。
そもそもDateクラスはスレッドセーフでなく、LocalDateTimeクラスはスレッドセーフなので、そういった面でもやっぱり新しいAPIは色々といい感じになっているのだと思います。

まとめますと、日時オブジェクトによって選択肢は変わりますが、

  • Dateならば、「FastDateFormat」
    • 外部ライブラリ導入のハードルが高いなら…他のAPIを使用、ただしスレッドセーフに要注意
  • LocalDateTime/ZonedDateTimeならば、「DateTimeFormatter」

と言えるかと思います。

どこかで何かの参考になれば幸いです!

お問い合わせ先

執筆者プロフィール

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