こんにちは。 エキサイト株式会社の三浦です。
アプリケーションを書くとき、日時データを扱うことはよくあります。
その際、「常に日本時間しか扱わない」などの状況であればいいですが、場合によっては「世界標準時と日本時間を相互に変換する」など、複数のタイムゾーン間の変換が必要になることもあるでしょう。
今回はJavaにおいて、あるローカル日時文字列を、タイムゾーンを変更した上でローカル日時型データに変換する方法について説明します。
タイムゾーンとローカル日時
時間にはタイムゾーンが存在します。
これは世界標準時を基準として時差がどのくらいあるかを表しているもので、日本であれば +9時間
です。
日時を示すフォーマットの1つである「ISO 8601」を使うと、 +9時間
のタイムゾーンであれば以下のように表現されます。
2022-10-25T10:00:00+09:00
コーディングをする際も、日時を扱うのであればタイムゾーンは基本的に気にする必要があるものですが、例えば「絶対に日本時間しか使わない」というプログラムであれば、日本時間であることを暗黙の了解とした上で、タイムゾーンを省略した「ローカル日時」を使うことが出来ます。
2022-10-25T10:00:00
ローカル日時の方がシンプルなので、こちらを使う場合も多々あると思われますが、例えば外部のサービスやAPIを使用する際などに、「世界標準時のローカル日時でしか日時データを返さない」という場合もあるでしょう。
それでもなおコード内部で世界標準時以外(日本時間など)のローカル日時しか使用したくない場合は、受け取ったタイミングで「世界標準時のローカル日時文字列 -> 日本時間のローカル日時データ」への変更が必要になります。
では、Javaでそのような変更をするにはどうすればよいのでしょうか?
Javaで、ローカル日時文字列からタイムゾーンを変更してローカル日時型データを取得する方法
Javaでローカル日時を扱う際は、 LocalDateTime
という型を使用します。
final LocalDateTime localDateTime = LocalDateTime.parse("2022-10-25T10:00:00");
コードからも分かる通り、これはタイムゾーンを考慮していない、ローカル日時のための型です。
そのため、これだけではタイムゾーンの変換を行うことが出来ません。
変換を行うには、 ZonedDateTime
という、タイムゾーンも考慮した日時のための型を使用する必要があります。
final ZonedDateTime zonedDateTime = ZonedDateTime.parse("2022-10-25T10:00:00+09:00");
具体的には、以下の方法で変更します。
final String localDateTimeString = "2022-10-25T10:00:00"; final LocalDateTime localDateTime = ZonedDateTime .parse( localDateTimeString, DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.of("UTC")) ) // localDateTimeStringを、UTC(世界標準時)の日時と考えるようにした上でタイムゾーン日時型に変換する .withZoneSameInstant(ZoneId.of("Asia/Tokyo")) // タイムゾーンを日本時間に変更する .toLocalDateTime(); // ローカル日時型データに変換する
これを実行すると、 localDateTime
には以下のデータが入ってきます。
2022-10-25T19:00
2022-10-25T10:00:00
を世界標準時として考慮するようにしたので、日本時間に変更した結果、 +9時間
された正しい日時が返ってきました。
最後に
グローバルなサービスだったりすると、返却される日時データが世界標準時なのは珍しいことではありません。
日時データ周りはちゃんと扱わないとバグの原因にもなりうるため、ローカル日時としてデータを扱う際は気をつけるようにし、必要に応じて適宜変換を行っていくようにしましょう。
ちなみに、サーバやコンテナ自体にもタイムゾーン設定をすることが出来ます。 例えばアプリケーション内で日本時間を扱う場合は、アプリケーションが動くサーバやコンテナ自体のタイムゾーン設定も日本時間にしておくと良いでしょう。