Java

https://javazuki.com/articles/date-calendar-convert-to-datetime.html

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

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

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 A: 参考

関連記事リンク