JavaのZonedDateTimeでタイムゾーン付きの日付・時刻を正確に扱う方法
生徒
「Javaで国ごとの時間を扱いたいんですが、タイムゾーンってどうやって指定するんですか?」
先生
「タイムゾーンを扱うにはZonedDateTimeというクラスを使うのが便利ですよ。世界各地のタイムゾーンに対応しています。」
生徒
「それって、普通のLocalDateTimeとは何が違うんですか?」
先生
「とても良いところに気づきましたね。LocalDateTimeはタイムゾーンを持たないのに対して、ZonedDateTimeはタイムゾーン情報を含む日付・時刻なんです。」
1. JavaのZonedDateTimeとは?
ZonedDateTimeは、Javaのjava.timeパッケージに属するクラスで、「日付・時刻・タイムゾーン」の3つをすべて含む強力なクラスです。これを使うことで、UTCやJST(日本標準時)、PST(アメリカ西海岸時間)などのタイムゾーンに対応した時刻の取得や表示が可能になります。
Javaで世界中のユーザーに対応するアプリケーションを作る場合、タイムゾーンを意識した設計が重要です。ZonedDateTimeは、タイムゾーンを考慮した処理を行いたいときの定番クラスです。
2. ZonedDateTimeの基本的な使い方
例えば現在の日本時間(JST)を取得したい場合、次のように記述します。
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class TimeExample {
public static void main(String[] args) {
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("日本時間: " + nowInTokyo);
}
}
日本時間: 2025-09-03T14:30:15.123+09:00[Asia/Tokyo]
ZoneId.of("Asia/Tokyo")で、明示的に「東京(JST)」のタイムゾーンを指定しています。タイムゾーンの指定には、IANAで定められたタイムゾーンIDを使用します。
3. ZonedDateTimeのタイムゾーン変換(タイムゾーンを変更する)
現在の日本時間を、たとえばアメリカのロサンゼルス時間(PST)に変換したい場合は、withZoneSameInstant()を使います。
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class ZoneConversionExample {
public static void main(String[] args) {
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
ZonedDateTime laTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println("東京時間: " + tokyoTime);
System.out.println("ロサンゼルス時間: " + laTime);
}
}
東京時間: 2025-09-03T14:30:15.123+09:00[Asia/Tokyo]
ロサンゼルス時間: 2025-09-02T22:30:15.123-07:00[America/Los_Angeles]
同じ瞬間を別のタイムゾーンで表すことができるため、グローバルアプリでは非常に重要な機能です。
4. ZonedDateTimeとフォーマットの指定
ZonedDateTimeはDateTimeFormatterと一緒に使うことで、自由な形式で日付を表示できます。
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class FormatterExample {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z VV");
String formatted = now.format(formatter);
System.out.println("フォーマット済み: " + formatted);
}
}
フォーマット済み: 2025-09-03 14:30:15 JST Asia/Tokyo
zは略称(JSTなど)、VVはタイムゾーンID(Asia/Tokyo)を表します。
5. ZonedDateTimeとLocalDateTimeの違い
初心者が混乱しやすいのがLocalDateTimeとの違いです。LocalDateTimeはタイムゾーン情報を含まないため、「どこの国の時間か」が分かりません。一方、ZonedDateTimeはタイムゾーン込みなので、国や地域ごとに正確な時刻管理ができます。
たとえばサーバーはUTC、ユーザーはJSTで処理したいといった場合にはZonedDateTimeが大活躍します。
6. 代表的なZoneId(タイムゾーンID)一覧
Javaでは多くのタイムゾーンIDが定義されています。以下に代表的なものを紹介します:
Asia/Tokyo:日本UTC:協定世界時America/New_York:アメリカ東部Europe/London:イギリスAsia/Shanghai:中国
タイムゾーンIDは厳密に定義されているため、正しい文字列を使用することが重要です。
7. ZonedDateTimeの注意点とベストプラクティス
複数タイムゾーンを扱うアプリでは、以下の点に注意しましょう:
- 保存はUTC、表示はユーザーのタイムゾーンに変換
- 外部APIと連携する場合は
InstantやZonedDateTimeで受け渡す - システムでタイムゾーンを統一しておくとバグが減る
また、Instantとの相互変換も可能です。
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class InstantConversion {
public static void main(String[] args) {
Instant now = Instant.now();
ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Tokyo"));
System.out.println("Instant → ZonedDateTime: " + zdt);
}
}