Javaの日付API:java.time.*を使ってみます

こんにちは、さるまりんです🐒

新しいJavaといっても、もうかなり経ちますが、Java 8以降は新しいものが色々とあります。その中でもjava.time.*。あまり使ってなくて僕にとってはほぼ未知なのでまとめてここでメモしておきたいと思います。

基本型とよく使うクラスたち

LocalDate

年月日、2025-07-07などを扱います。

LocalDate date = LocalDate.now();
LocalTime

こちらは時分秒、07:30:00などです。

LocalTime time = LocalTime.now();
LocalDateTime

DateTime、日付と時間を合わせたものです。 2025-07-07T07:30:00のような値です。

LocalDateTime dateTime = LocalDateTime.now();
ZonedDateTime

タイムゾーン付きの日時です。
2025-07-07T07:30:00+0900[Asia/Tokyo]、これは日本時間の例です。

ZonedDateTime zoned = ZonedDateTime.now();
Instant

これはエポック秒(UTC)です。
日本時間2025-07-07 07:30の値はこちら→1751841000L。
これまではlongで表していたものがクラスとして用意されています。

Instant instant = Instant.now();

日付・時間の加算・減算・比較

それぞれの例です。

日付について
LocalDate today = LocalDate.now(); // 今日
LocalDate nextWeek = today.plusWeeks(1); // 1週間後
LocalDate yesterday = today.minusDays(1); // 1日前

boolean isBefore = yesterday.isBefore(today); // 「昨日」は「今日」より前?
時間について
LocalTime now = LocalTime.of(10, 30); // 10:30
LocalTime later = now.plusHours(2).minusMinutes(15); // 2時間足して15分引く
boolean isAfter = later.isAfter(now); // 「後」は「今」より後?
日時について
LocalDateTime current = LocalDateTime.now(); // 現在の日時
LocalDateTime past = current.minusDays(2).minusHours(5); // 2日引いて、さらに5時間引く
Duration duration = Duration.between(past, current); // その差を求める
long minutes = duration.toMinutes(); // 分にすると?

Duration、時間の距離です。DBにあるintervalと似たようなものですね。

計算する時、以前ならDateからCalendarにして、足して引いてDateに戻してとかやってましたが、これは簡単ですね。

フォーマットとパース

以前はjava.text.DateFormatSimpleDateFormatを使ってました。
DateTimeFormatterというのが登場していますね。
こちらでも似たように処理できるようです。

LocalDate date = LocalDate.of(2024, 7, 1);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String formatted = date.format(fmt); // → "2024/07/01"

LocalDate parsed = LocalDate.parse("2024/07/01", fmt);

データベースとのやり取り:旧APIとの変換

java.time.*を使って開発していても、JDBC や ORM(JPAなど)と連携する時には java.sql.DateTimestampが必要になることがあります。そんなときの変換はこんな風にします。

LocalDate ⇔ java.sql.Date
LocalDate localDate = LocalDate.now();
java.sql.Date sqlDate = java.sql.Date.valueOf(localDate);

LocalDate restored = sqlDate.toLocalDate();
LocalTime ⇔ java.sql.Time
LocalTime localTime = LocalTime.now();
java.sql.Time sqlTime = java.sql.Time.valueOf(localTime);

LocalTime restored = sqlTime.toLocalTime();
LocalDateTime ⇔ java.sql.Timestamp
LocalDateTime localDateTime = LocalDateTime.now();
java.sql.Timestamp sqlTimestamp = java.sql.Timestamp.valueOf(localDateTime);

LocalDateTime restored = sqlTimestamp.toLocalDateTime();
Instantとの変換(UTCベース)

エポック秒はこんな風に変換できます。

Instant now = Instant.now();
Timestamp ts = Timestamp.from(now);

Instant restored = ts.toInstant();

JPAを使う場合は

JPA 2.2 以降ではLocalDateLocalDateTimeなどjava.time系の型をJDBCドライバが対応ていれば、そのまま使うことができます。

@Entity
public class Event {
    @Id
    private Long id;

    private LocalDate eventDate;
    private LocalDateTime createdAt;
}

それ以前のJPAや対応していないドライバを使っている場合は、変換用の@Converterを使って手動で繋いであげる必要があります。

簡単、シンプルですが、最初は慣れないので、どんどん使っていくのがいいと思いました。
java.util.Datejava.sql.Dateもあって、java.time.*も。うまく使って良いプログラムをかいていきたいです。古いコードもjava.time.*で書き直してみると、読みやすさも安全性も上がってくるかも。

読んでくださってありがとうございました。

それではまた!