Date/Calendar↔Date And Time API系変換のまとめ

Instantを介することで変換可能。その手順のまとめ。

執筆時バージョン
Java

Java SE 8

Date/Calendar↔Date And Time API系の変換は、Instantを介して行う。それぞれのクラスでInstantを直接扱えるのかどうかなどが異なるため、手順をまとめる。

Date/Calendar→Date And Time API系の変換

DateOrCalendarからXXXDateTimeへの変換
Figure 1. Date/CalendarからDate And Time API系への変換

Date/CalendarからDate And Time API系へ変換する場合は、まずXXXDateTimeへの変換を考える。「LocalDate」「LocalTime」「Year」「YearMonth」などはXXXDateTimeから変換メソッドが用意されているので、とりあえずXXXDateTimeにしてしまう。

Date/CalendarからXXXDateTimeへの変換はInstantを介して行う。Date/CalendarにはInstantを取得できるtoInstant()メソッドが、Java8から追加された。Instantはエポック時間からの経過秒が保持されている。ただしInstantだけでは表現したい時差やタイムゾーンが不明のため、XXXDateTimeにするには「ZoneId」or「ZoneOffset」が必要になる。システムデフォルトのZoneIdはZoneId.systemDefault()で取得できる。

Date→LocalDateTime

LocalDateTimeの場合、エポック秒から生成できるofEpochSecond()が用意されている。ただZoneIdからZoneOffsetを取得するのは手順が面倒なため、instantとzoneIdで生成できるofInstant()が用意されている。それを利用する。

Date→LocalDateTimeへの変換
Date date = new Date();

Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime converted = LocalDateTime.ofInstant(instant, zone);

Date→OffsetDateTime

OffsetDateTimeの場合、「ZoneId」「ZoneOffset」のどちらからでも生成できる。ZoneIdはZoneOffsetの情報を取得できるので可能。

OffsetDateTimeへの変換(ZoneOffset利用)
Date date = new Date();

Instant instant = date.toInstant();
ZoneOffset offset = ZoneOffset.ofHours(9);
OffsetDateTime converted = instant.atOffset(offset);
OffsetDateTimeへの変換(ZoneId利用)
Date date = new Date();

Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
OffsetDateTime converted = OffsetDateTime.ofInstant(instant, zone);

Date→ZonedDateTime

ZonedDateTimeの場合、instantとzoneIdから生成できる。InstantクラスにもZonedDateTimeを生成できるファクトリがあるが、内部的に ZonedDateTime.ofInstant()呼び出すのでどちらでもいい。

ZonedDateTimeへの変換
Date date = new Date();

Instant instant = date.toInstant();
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime converted = ZonedDateTime.ofInstant(instant, zone);

Calendar→LocalDateTime,OffsetDateTime,ZonedDateTime

CalendarもtoInstant()があるのでInstantを介した変換が可能。instant取得後は同様の手順。

LocalDateTimeへの変換
Calendar calendar = Calendar.getInstance();

Instant instant = calendar.toInstant();
ZoneId zone = ZoneId.systemDefault();
LocalDateTime converted = LocalDateTime.ofInstant(instant, zone);

Date And Time API系→Date/Calendarの変換

XXXDateTimeからDateOrCalendarへの変換
Figure 2. Date And Time API系からDate/Calendarへの変換

Date And Time API系からDate/Calendarへ変換する場合は、まず「OffsetDateTime」「ZonedDateTime」への変換を考える。Instantを取得することでDate/Calendarへの変換が可能になる。ただし、InstantからCalendarを直接生成することができない。Dateを生成してからCalendarへ変換する手順になる。

Date/Calendarへの変換においては、LocalDateTimeが直接Instatntを作れない。LocalDateTimeが示している日時がどの時差あるいはタイムゾーンなのかの情報を持たないため、Instantは生成できないことになる。よって「LocalDate」「LocalTime」「Year」「YearMonth」などと同様に、「OffsetDateTime」「ZonedDateTime」を経由してInstantを生成する。

LocalDateTime→Date

LocalDateTimeからInstantは直接生成できないので、OffsetDateTime かZonedDateTimeを経由する。

LocalDateTime→Dateへの変換
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);

Instant instant = zonedDateTime.toInstant();
Date date = Date.from(instant);

OffsetDateTime→Date

OffsetDateTimeはInstantを生成できるので、そのまま変換可能。

OffsetDateTime→Dateへの変換
OffsetDateTime offsetDateTime = OffsetDateTime.now();
Instant instant = offsetDateTime.toInstant();
Date date = Date.from(instant);

ZonedDateTime→Date

ZonedDateTimeはInstantを生成できるので、そのまま変換可能。

ZonedDateTime→Dateへの変換
ZonedDateTime zonedDateTime = ZonedDateTime.now();
Instant instant = zonedDateTime.toInstant();
Date date = Date.from(instant);

LocalDateTime,OffsetDateTime,ZonedDateTime→Calendar

CalendarはInstantを生成できるが、InstantからCalendarを生成できない。Dateを経由して、Date→Calendar変換を行う。「OffsetDateTime」「ZonedDateTime」も同様の手順。

LocalDateTime→Calendarへの変換
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);

Instant instant = zonedDateTime.toInstant();
Date date = Date.from(instant);

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);

GregorianCalendar↔ZonedDateTimeの変換

Calendarの中でもGregorianCalendarのみ特殊で、ZonedDateTimeと相互変換が可能。

GregorianCalendarがグレゴリオ暦かつタイムゾーンを保持しているので、ZonedDateTimeととても近いため。ただしGregorianCalendarとZonedDateTimeはユリウス/グレゴリオ暦の切換え日のサポート有無が異なるため、そこだけ注意。

GregorianCalendar→ZonedDateTimeへの変換
GregorianCalendar gregorianCalendar = new GregorianCalendar();
ZonedDateTime converted = gregorianCalendar.toZonedDateTime();
ZonedDateTime→GregorianCalendarへの変換
ZonedDateTime zonedDateTime = ZonedDateTime.now();
GregorianCalendar gregorianCalendar = GregorianCalendar.from(zonedDateTime);

Appendix B: 改訂履歴

  • v1.0, 2016-07-12: 初稿