Java ZonedDateTime クラス
ZonedDateTime は Java 8 で導入された日時 API (java.time パッケージ) の重要なクラスで、タイムゾーン付きの日付と時刻を表します。このクラスは LocalDateTime と ZoneId を組み合わせ、特定のタイムゾーンにおける時点を正確に表すことができます。
主な特徴
- 日付(年、月、日)を含む
- 時刻(時、分、秒、ナノ秒)を含む
- タイムゾーン情報を含む
- 不変でスレッドセーフなクラスです
- タイムゾーン変換と夏時間の自動調整をサポートします
ZonedDateTime の作成方法
1. 現在時刻を使用して作成
例
// 現在のシステム既定タイムゾーンの日時を取得
ZonedDateTime now = ZonedDateTime.now();
// 指定したタイムゾーンの現在日時を取得
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
ZonedDateTime now = ZonedDateTime.now();
// 指定したタイムゾーンの現在日時を取得
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
2. 構成要素から作成
例
// 年、月、日、時、分、秒、タイムゾーンを指定
ZonedDateTime customDateTime = ZonedDateTime.of(
2023, 12, 25, 15, 30, 0, 0,
ZoneId.of("America/New_York")
);
ZonedDateTime customDateTime = ZonedDateTime.of(
2023, 12, 25, 15, 30, 0, 0,
ZoneId.of("America/New_York")
);
3. LocalDateTime と ZoneId の組み合わせから作成
例
LocalDateTime localDateTime = LocalDateTime.of(2023, 6, 15, 10, 30);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);
よく使う操作メソッド
1. 時刻情報の取得
例
ZonedDateTime zdt = ZonedDateTime.now();
int year = zdt.getYear(); // 年
Month month = zdt.getMonth(); // 月
int day = zdt.getDayOfMonth(); // 日
int hour = zdt.getHour(); // 時
int minute = zdt.getMinute(); // 分
int second = zdt.getSecond(); // 秒
ZoneId zone = zdt.getZone(); // タイムゾーン
int year = zdt.getYear(); // 年
Month month = zdt.getMonth(); // 月
int day = zdt.getDayOfMonth(); // 日
int hour = zdt.getHour(); // 時
int minute = zdt.getMinute(); // 分
int second = zdt.getSecond(); // 秒
ZoneId zone = zdt.getZone(); // タイムゾーン
2. 時刻の加算・減算操作
例
ZonedDateTime zdt = ZonedDateTime.now();
// 1日加算
ZonedDateTime tomorrow = zdt.plusDays(1);
// 2時間減算
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);
// 3週間加算
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);
// 1日加算
ZonedDateTime tomorrow = zdt.plusDays(1);
// 2時間減算
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);
// 3週間加算
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);
3. タイムゾーン変換
例
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
// ニューヨーク時刻に変換
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// UTC時刻に変換
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);
// ニューヨーク時刻に変換
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// UTC時刻に変換
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);
実践的な使用例
1. 2つのタイムゾーンの時差を計算
例
ZonedDateTime londonTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
// 時差(時間)を計算
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("ロンドンとシドニーの現在の時差: " + hoursBetween + "時間");
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
// 時差(時間)を計算
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("ロンドンとシドニーの現在の時差: " + hoursBetween + "時間");
2. タイムゾーンをまたぐ会議時刻の処理
例
// ニューヨークの会議時刻は午後3時
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
LocalDate.now(),
LocalTime.of(15, 0),
ZoneId.of("America/New_York")
);
// 東京時刻に変換
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("東京の参加者は現地時刻: " + meetingTimeTokyo);
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
LocalDate.now(),
LocalTime.of(15, 0),
ZoneId.of("America/New_York")
);
// 東京時刻に変換
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("東京の参加者は現地時刻: " + meetingTimeTokyo);
3. 夏時間の処理
例
// ニューヨークの夏時間切替前後の時刻
ZonedDateTime beforeDST = ZonedDateTime.of(
LocalDateTime.of(2023, 3, 11, 1, 30),
ZoneId.of("America/New_York")
);
ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("実際の時差: " +
Duration.between(beforeDST, afterDST).toHours() + "時間");
ZonedDateTime beforeDST = ZonedDateTime.of(
LocalDateTime.of(2023, 3, 11, 1, 30),
ZoneId.of("America/New_York")
);
ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("実際の時差: " +
Duration.between(beforeDST, afterDST).toHours() + "時間");
ZonedDateTime と他の日時クラスとの変換
1. Instant への変換
例
ZonedDateTime zdt = ZonedDateTime.now();
Instant instant = zdt.toInstant(); // UTCタイムスタンプに変換
Instant instant = zdt.toInstant(); // UTCタイムスタンプに変換
2. LocalDateTime への変換
例
ZonedDateTime zdt = ZonedDateTime.now();
LocalDateTime ldt = zdt.toLocalDateTime(); // タイムゾーン情報が失われる
LocalDateTime ldt = zdt.toLocalDateTime(); // タイムゾーン情報が失われる
3. Instant からの作成
例
Instant instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));
総合例
例
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
// 1. 現在のタイムゾーンの現在時刻を取得
ZonedDateTime now = ZonedDateTime.now();
System.out.println("現在のタイムゾーンの時刻: " + now);
// 2. 指定したタイムゾーンの現在時刻を取得
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("東京時刻: " + tokyoTime);
// 3. 特定のタイムゾーン付き時刻を作成
ZonedDateTime specificTime = ZonedDateTime.of(
2023, 5, 15, 10, 30, 0, 0,
ZoneId.of("America/New_York")
);
System.out.println("ニューヨークの特定時刻: " + specificTime);
// 4. タイムゾーン変換
ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("対応するロンドン時刻: " + londonTime);
// 5. フォーマットして出力
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("フォーマットされた時刻: " + now.format(formatter));
// 6. 各要素の情報を取得
System.out.println("タイムゾーン: " + now.getZone());
System.out.println("年: " + now.getYear());
System.out.println("月: " + now.getMonth());
System.out.println("時: " + now.getHour());
}
}
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
// 1. 現在のタイムゾーンの現在時刻を取得
ZonedDateTime now = ZonedDateTime.now();
System.out.println("現在のタイムゾーンの時刻: " + now);
// 2. 指定したタイムゾーンの現在時刻を取得
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("東京時刻: " + tokyoTime);
// 3. 特定のタイムゾーン付き時刻を作成
ZonedDateTime specificTime = ZonedDateTime.of(
2023, 5, 15, 10, 30, 0, 0,
ZoneId.of("America/New_York")
);
System.out.println("ニューヨークの特定時刻: " + specificTime);
// 4. タイムゾーン変換
ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("対応するロンドン時刻: " + londonTime);
// 5. フォーマットして出力
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("フォーマットされた時刻: " + now.format(formatter));
// 6. 各要素の情報を取得
System.out.println("タイムゾーン: " + now.getZone());
System.out.println("年: " + now.getYear());
System.out.println("月: " + now.getMonth());
System.out.println("時: " + now.getHour());
}
}
出力結果は次のようになります:
当前时区时间: 2025-05-01T11:29:07.411467+08:00[Asia/Shanghai] 东京时间: 2025-05-01T12:29:07.417938+09:00[Asia/Tokyo] 纽约特定时间: 2023-05-15T10:30-04:00[America/New_York] 对应的伦敦时间: 2023-05-15T15:30+01:00[Europe/London] 格式化时间: 2025-05-01 11:29:07 CST 时区: Asia/Shanghai 年份: 2025 月份: MAY 小时: 11
ベストプラクティス
- 保存と転送:データベース保存やネットワーク転送時は、Instant または UTC 時刻の ZonedDateTime を使用することを推奨します
- 表示:ユーザーインターフェースに表示するときだけローカルタイムゾーンに変換します
- 比較:異なるタイムゾーンの時刻を比較するときは、同じタイムゾーンまたは Instant に変換してから行います
- 夏時間:単純なオフセット(例:"-05:00")ではなく、常に完全なタイムゾーンID(例:"America/New_York")を使用します
ZonedDateTime はタイムゾーンに敏感なアプリケーションを扱うための強力なツールであり、正しく使用することで多くの一般的な日時問題を回避できます。
静的ファクトリメソッド
| メソッド | 説明 | 例 |
|---|---|---|
static ZonedDateTime now() |
現在のタイムゾーンの現在日時を取得 | ZonedDateTime.now() |
static ZonedDateTime now(ZoneId zone) |
指定したタイムゾーンの現在日時を取得 | ZonedDateTime.now(ZoneId.of("Asia/Shanghai")) |
static ZonedDateTime of(int year, int month, int day, int hour, int minute, int second, int nano, ZoneId zone) |
パラメータを指定して作成 | ZonedDateTime.of(2023, 6, 15, 14, 30, 0, 0, ZoneId.of("GMT+8")) |
static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) |
LocalDate、LocalTime、タイムゾーンを組み合わせて作成 | ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault()) |
static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone) |
LocalDateTime とタイムゾーンから作成 | ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/New_York")) |
static ZonedDateTime ofInstant(Instant instant, ZoneId zone) |
Instant とタイムゾーンから作成 | ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")) |
static ZonedDateTime parse(CharSequence text) |
文字列から解析 | ZonedDateTime.parse("2023-06-15T14:30:45+08:00[Asia/Shanghai]") |
static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) |
指定したフォーマットで解析 | ZonedDateTime.parse("2023-06-15 14:30 CST", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z")) |
日時情報の取得
| メソッド | 説明 | 例 |
|---|---|---|
int getYear() |
年を取得 | 2023 |
Month getMonth() |
月(Month 列挙型)を取得 | Month.JUNE |
int getMonthValue() |
月の値(1-12)を取得 | 6 |
int getDayOfMonth() |
月内の日数を取得 | 15 |
int getDayOfYear() |
年内の日数を取得 | 166 |
DayOfWeek getDayOfWeek() |
曜日(DayOfWeek 列挙型)を取得 | DayOfWeek.THURSDAY |
int getHour() |
時(0-23)を取得 | 14 |
int getMinute() |
分(0-59)を取得 | 30 |
int getSecond() |
秒(0-59)を取得 | 45 |
int getNano() |
ナノ秒を取得 | 0 |
ZoneId getZone() |
タイムゾーンを取得 | Asia/Shanghai |
ZoneOffset getOffset() |
タイムゾーンオフセットを取得 | +08:00 |
日時操作
| メソッド | 説明 | 例 |
|---|---|---|
ZonedDateTime plusDays(long days) |
日数を加算 | zdt.plusDays(5) |
ZonedDateTime plusHours(long hours) |
時間を加算 | zdt.plusHours(2) |
ZonedDateTime plusMinutes(long minutes) |
分を加算 | zdt.plusMinutes(30) |
ZonedDateTime plusSeconds(long seconds) |
秒を加算 | zdt.plusSeconds(45) |
ZonedDateTime plusNanos(long nanos) |
ナノ秒を加算 | zdt.plusNanos(1000000) |
ZonedDateTime minusDays(long days) |
日数を減算 | zdt.minusDays(5) |
ZonedDateTime minusHours(long hours) |
時間を減算 | zdt.minusHours(2) |
ZonedDateTime minusMinutes(long minutes) |
分を減算 | zdt.minusMinutes(30) |
ZonedDateTime minusSeconds(long seconds) |
秒を減算 | zdt.minusSeconds(45) |
ZonedDateTime minusNanos(long nanos) |
ナノ秒を減算 | zdt.minusNanos(1000000) |
ZonedDateTime withYear(int year) |
年を変更 | zdt.withYear(2024) |
ZonedDateTime withMonth(int month) |
月を変更 | zdt.withMonth(12) |
ZonedDateTime withDayOfMonth(int day) |
月内の日数を変更 | zdt.withDayOfMonth(1) |
ZonedDateTime withHour(int hour) |
時を変更 | zdt.withHour(0) |
ZonedDateTime withMinute(int minute) |
分を変更 | zdt.withMinute(0) |
ZonedDateTime withSecond(int second) |
秒を変更 | zdt.withSecond(0) |
ZonedDateTime withNano(int nano) |
ナノ秒を変更 | zdt.withNano(0) |
ZonedDateTime withZoneSameInstant(ZoneId zone) |
タイムゾーンを変換(同じ瞬間を保持) | zdt.withZoneSameInstant(ZoneId.of("UTC")) |
ZonedDateTime withZoneSameLocal(ZoneId zone) |
タイムゾーンを変換(ローカル時刻を保持) | zdt.withZoneSameLocal(ZoneId.of("UTC")) |
変換メソッド
| メソッド | 説明 | 例 |
|---|---|---|
LocalDate toLocalDate() |
LocalDate に変換 | zdt.toLocalDate() |
LocalTime toLocalTime() |
LocalTime に変換 | zdt.toLocalTime() |
LocalDateTime toLocalDateTime() |
LocalDateTime に変換 | zdt.toLocalDateTime() |
OffsetDateTime toOffsetDateTime() |
OffsetDateTime に変換 | zdt.toOffsetDateTime() |
Instant toInstant() |
Instant に変換 | zdt.toInstant() |
比較メソッド
| メソッド | 説明 | 例 |
|---|---|---|
boolean isAfter(ChronoZonedDateTime<?> other) |
指定された日時の後かどうか | zdt1.isAfter(zdt2) |
boolean isBefore(ChronoZonedDateTime<?> other) |
指定された日時の前かどうか | zdt1.isBefore(zdt2) |
boolean isEqual(ChronoZonedDateTime<?> other) |
指定された日時と等しいかどうか | zdt1.isEqual(zdt2) |
int compareTo(ChronoZonedDateTime<?> other) |
2つの日時を比較する | zdt1.compareTo(zdt2) |
フォーマットと文字列変換
| メソッド | 説明 | 例 |
|---|---|---|
String format(DateTimeFormatter formatter) |
文字列にフォーマットする | zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME) |
String toString() |
ISO形式の文字列に変換する | "2023-06-15T14:30:45+08:00[Asia/Shanghai]" |