「LocalDateTime」「OffsetDateTime」「ZonedDateTime」のどれを使うべきか

Date And Time APIのどの日時クラスを使えばいいのかわからなくなったら、参考にて下さい。

Date And Time APIで日時クラスが3つに増えた。それぞれの違いは難しくないが、いざ使おうとすると迷うことが多い。どれをどのように使っていくべきかをまとめる。

基本的にはLocalDateTimeを使う

そもそも時差・タイムゾーンなんて扱っていない

かなりのプログラムがこれに該当する。特に日本の場合、時間帯は1つしかなく夏時間などもない。なのでそもそもタイムゾーンをこれまでも本気で扱っていないことも多い。

これまでのCalendarクラスはタイムゾーンを持っている。なので同じくタイムゾーンを持つZonedDateTimeを使うという考え方もあるかもしれないが、本当にそうなのかは熟考が必要。Calendarクラスを使っていてもタイムゾーン情報を持たされていたという感じで、実際には本気でタイムゾーンは扱っていない場合もある。

本質的に時差・タイムゾーンを扱っていないのに、Date And Time APIになるからといって背伸びしてこれから扱う必要も無い。LocalDateTimeで十分。

tz databaseを更新できるのか?

ZonedDateTimeを利用するということは、タイムゾーン情報をしっかり更新しないと意味が無い。タイムゾーンの情報は頻繁に変更される。夏時間の導入などは政治的要素もからんでくるため、鶴の一声的なものでも変わることもある。

Javaではtz databaseを使ってタイムゾーンを管理する。Javaのバージョンアップ時にも更新されるが、tz database更新時に必ずしもJavaがバージョンアップするとも限らないので、いざとなったら自力でtz databaseをアップデートすることが必要になる。

これを本気で運用しているシステムはそう多くない。頻度の問題はあるにせよZonedDateTimeを使うということはこれに対処するということ。それが仕様なら覚悟して使っていくことになる。

意外と使えるOffsetDateTime

「LocalDateTime」「ZonedDateTime」に比べると、中途半端に思われてしまう「OffsetDateTime」は意外と使える。特にWebAPIやJavaScriptによるJSONのやり取りなどでは、タイムゾーンまで意識する必要は無いので時差情報だけを持つISO8601形式が重宝される。

そう考えるとシステムとしては、変わりやすいタイムゾーンはリスクが大きいので、扱うとしても(入出力で必要な部分は別として)時差にしておきたい。というよりOffsetDateTimeの登場で、時差だけを扱えるようになったことがとても大きい。

システムは同一時差のLocalDateTimeで、入出力で時差・タイムゾーンを吸収する

時差・タイムゾーンを扱うとしてもLocalDateTimeが基本になる。(これは筆者の一案なので、参考までに)

まずプログラム内はLocalDateTimeに統一する。時差やタイムゾーンをプログラム内部で意識する範囲を入出力のみに限定する。同時にプログラム内のデフォルト(タイムゾーンではなく)時差を決めておく。タイムゾーンは変更される可能性が高いので、あくまでも時差。

入力ではUIあるいはDBの時差・タイムゾーンに合わせる形で受け取り、システム内の時差に変換、さらにLocalDateTimeにしてしまう。出力ではLocalDateTimeから直接変換しても構わない。こうすることで色々な時差・タイムゾーンに包括的に対応できる。

BigDecimal同様にシステムの全体を考えないとうまくいかない。DBの時間も重要だし、入力画面でユーザーがどのタイムゾーンとして入力するのかも重要になる。