はじめに
こんにちは。
プログラミング初心者wakinozaと申します。
Java勉強中に調べたことを記事にまとめています。
十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
間違い等あれば、指摘いただけると助かります。
記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。
対象読者
- Javaを勉強中の方
- 「Date and Time API」について知りたい方
記事のテーマ
- 「Date and Time API」のローカル日時を扱うクラスを開発でよく使います。しかし、APIの種類が多くて、いちいち公式リファレンスで検索するのが面倒になってきました。そこで、よく使いそうなローカル日時クラスのメソッドやAPIを、自分用にまとめてみました
- 前編である前回は、「Date and Time API」の概要と、インスタンスの生成、インスタンスから情報や文字列を取得する方法をまとめました
- 今回は、LocalDateTimeインスタンスの操作に関わるメソッドをまとめました
目次
1. インスタンスの日時情報を個別に設定
2. 日時の計算
3. 日時の前後比較
4. TemporalAdjusterによる日時の算出
本文
1. インスタンスの日時情報を個別に設定
LocalDateTimeインスタンス生成後に、日時情報を変更したい場合は、「with〇〇メソッド」を利用します。
とはいえ、LocalDateTimeはイミュータブルのため、一度インスタンスを生成したら、後から内部の日時情報を変更できません。
with〇〇メソッドは、元のインスタンスの日時情報を変更するのではなく、指定された値を持つ新しいインスタンスを生成し、その参照を返します。元のインスタンスの情報は変更されません。
日時情報 | メソッド | 説明 |
---|---|---|
年 | public LocalDateTime withYear(int year) | 年を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
月 | public LocalDateTime withMonth(int month) | 月を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
日 | public LocalDateTime withDayOfMonth(int dayOfMonth) | 日を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
時 | public LocalDateTime withHour(int hour) | 時を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
分 | public LocalDateTime withMinute(int minute) | 分を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
秒 | public LocalDateTime withSecond(int second) | 秒を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
ナノ秒 | public LocalDateTime withNano(int nanoOfSecond) | ナノ秒を引数の値に設定し、新しいインスタンスを生成してその参照を返します |
コード例で見てみましょう。
LocalDateTime dateTime = LocalDateTime.of(2000, 1, 1, 1, 1, 1, 1);
System.out.println(dateTime); //結果:2000-01-01T01:01:01.001
LocalDateTime withYear = dateTime.withYear(2025);
System.out.println(withYear); //結果:2025-01-01T01:01:01.001
LocalDateTime withMonth = dateTime.withMonth(12);
System.out.println(withMouth); //結果:2000-12-01T01:01:01.001
LocalDateTime withDayOfMonth = dateTime.withDayOfMonth(31);
System.out.println(withDayOfMonth); //結果:2000-01-31T01:01:01.001
LocalDateTime withHour = dateTime.withHour(12);
System.out.println(withHour); //結果:2000-01-01T12:01:01.001
LocalDateTime withMinute = dateTime.withMinute(55);
System.out.println(withMinute); //結果:2000-01-01T01:55:01.001
System.out.println("元のインスタンス:" + dateTime);
//元のインスタンス:2000-01-01T01:01:01.001
日時情報が引数で指定した値に設定され、新しいインスタンスが生成されています。
元となったインスタンスは、メソッド呼び出し後も、変更されません。
また、with〇〇メソッドは以下のようにメソッドをチェーンして利用することができます。
LocalDateTime newDateTime = dateTime.withYear(2025).withMonth(12).withDayOfMonth(31);
System.out.println(newDateTime); //結果:2025-12-31T01:01:01.001
2.日時の計算
インスタンスが持つ日時情報を元に計算を行う場合は、plus〇〇メソッドやminus〇〇メソッドを利用します。
これらメソッドも、元のインスタンスの日時情報を変更するのではなく、値を加算・減算した新しいインスタンスを生成してその参照を返します。
日時情報 | 加算メソッド | 説明 |
---|---|---|
年 | public LocalDateTime plusYears(long years) | 年を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
月 | public LocalDateTime plusMonths(long months) | 月を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
日 | public LocalDateTime plusDays(long days) | 日を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
時 | public LocalDateTime plusHours(long hours) | 時を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
分 | public LocalDateTime plusMinutes(long minutes) | 分を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
秒 | public LocalDateTime plusSeconds(long seconds) | 秒を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
ナノ秒 | public LocalDateTime plusNanos(long nanos) | ナノ秒を引数の値だけ加算し、新しいインスタンスを生成してその参照を返します |
日時情報 | 減算メソッド | 説明 |
---|---|---|
年 | public LocalDateTime minusYears(long years) | 年を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
月 | public LocalDateTime minusMonths(long months) | 月を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
日 | public LocalDateTime minusDays(long days) | 日を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
時 | public LocalDateTime minusHours(long hours) | 時を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
分 | public LocalDateTime minusMinutes(long minutes) | 分を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
秒 | public LocalDateTime minusSeconds(long seconds) | 秒を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
ナノ秒 | public LocalDateTime minusNanos(long nanos) | ナノ秒を引数の値だけ減算し、新しいインスタンスを生成してその参照を返します |
コード例で見てみましょう。
plus〇〇()メソッドやminus〇〇()メソッドも、メソッドチェーンして利用することができます。
LocalDateTime dateTime2 = LocalDateTime.of(2020, 1, 1, 1, 1, 1, 1);
System.out.println(dateTime2); //結果:2020-01-01T01:01:01.000000001
LocalDateTime newDateTime2 = dateTime2.minusYears(5).plusMonths(7).minusDays(9).plusHours(44);
System.out.println(newDateTime2); //結果:2015-07-24T21:01:01.000000001
System.out.println("元のインスタンス:" + dateTime2);
//元のインスタンス:2020-01-01T01:01:01.000000001
年や月の計算では、加算・減算した日付が無効な日付である可能性もあります。
その場合は、最後の有効な日付を返します。
例えば、閏年の2024年2月29日の1年後は、単純計算では「2025年2月29日」となります。しかし、2025年は閏年ではないため、「2025年2月29日」は無効な日付です。このような場合、メソッドは最後の有効な日付である「2025年2月28日」を返す仕様となっています。
月の計算も同様に、3月31日の1ヶ月後を計算すると「4月31日」という無効な日付となります。その場合、メソッドは「4月30日」を返します。
3. 日時の前後比較
インスタンス同士の前後関係を調べる場合のメソッドを紹介します。
メソッド | 説明 |
---|---|
public boolean isBefore(ChronoLocalDateTime> other) | このLocalDateTimeが、指定されたLocalDateTimeより前かどうかを判定する |
public boolean isAfter(ChronoLocalDateTime> other) | このLocalDateTimeが、指定されたLocalDateTimeより後かどうかを判定する |
public boolean isEqual(ChronoLocalDateTime> other) | このLocalDateTimeが、指定されたLocalDateTimeと等しいかどうかを判定する(タイムゾーンは考慮しない) |
コード例を見ていきましょう。
LocalDateTime date1 = LocalDateTime.of(2022, 6, 6, 0, 0);
LocalDateTime date2 = LocalDateTime.of(2022, 6, 12, 0, 0);
LocalDateTime date3 = LocalDateTime.of(2022, 6, 6, 0, 0);
boolean result1 = date1.isAfter(date2); // 結果:false
boolean result2 = date1.isBefore(date2); // 結果:true
boolean result3 = date1.isEqual(date2); // 結果:false
boolean result4 = date1.isEqual(date3); // 結果:true
引数のChronoLocalDateTimeは、 java.time.chrono.ChronoLocalDateTimeインターフェースのことです。
「Date and Time API」は私たちが普段使っている標準グレゴリオ暦以外に、和暦やタイ仏教歴など様々な暦体系をサポートしています。ちなみに、LocalDateTimeクラスは、実は標準グレゴリオ暦を扱うためのクラスです。
ChronoLocalDateTimeインターフェースは、特定の暦体系に依存しない日付と時間を表すインターフェースです。特定の暦体系を扱うLocalDateTimeなどのクラスは、すべてChronoLocalDateTimeインターフェースを実装しているため、ChronoLocalDateTimeインターフェースを引数とすることで、様々な暦体系の日時クラスを1つのシグネチャで扱うことができるのです。
とはいえ、実際の開発環境では、標準グレゴリオ暦で日時を扱う事例がほとんどです。そのため、特別な理由がない限り、ChronoLocalDateTimeの引数には「LocalDateTimeクラス」を渡します。
4. TemporalAdjusterによる日時の算出
実際の日付処理では、「月末日」や「その月の最後の金曜日」といった、やや複雑な日付調整が必要な場合もあります。
このような場合に用いるのが、 java.time.temporal.TemporalAdjusterインターフェースです。
TemporalAdjusterインターフェースは関数型インターフェースで、日付や時間オブジェクトを調整(adjust)するためのロジックを表現できます。
ラムダ式を使用して開発者独自の調整ロジックを作成することも可能ですが、TemporalAdjustersというヘルパークラスが、よく使われる調整ロジックをファクトリメソッドとして提供しているので、そちらを使うと良いでしょう。
TemporalAdjustersクラスのファクトリメソッドは、以下の通りです。
メソッド | 説明 |
---|---|
public static TemporalAdjuster firstDayOfYear() | その年の最初の日を返す |
public static TemporalAdjuster firstDayOfNextYear() | 翌年の最初の日を返す |
public static TemporalAdjuster firstDayOfMonth() | その月の最初の日を返す |
public static TemporalAdjuster firstDayOfNextMonth() | 翌月の最初の日を返す |
public static TemporalAdjuster firstInMonth(DayOfWeek dayOfWeek) | その月のうち、指定された曜日の最初の日を返す |
public static TemporalAdjuster lastDayOfYear() | その年の最後の日を返す |
public static TemporalAdjuster lastDayOfMonth() | その月の最後の日を返す |
public static TemporalAdjuster lastInMonth(DayOfWeek dayOfWeek) | その月のうち、指定された曜日の最後の日を返す |
public static TemporalAdjuster next(DayOfWeek dayOfWeek) | 指定された曜日と一致する直後の日を返す |
public static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek) | 指定された曜日と一致する直後の日(当日を含む)を返す |
public static TemporalAdjuster previous(DayOfWeek dayOfWeek) | 指定された曜日と一致する直前の日を返す |
public static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek) | 指定された曜日と一致する直前の日(当日を含む)を返す |
TemporalAdjusterによる日時の算出を利用する場合は、TemporalAdjustersクラスのファクトリメソッドでTemporalAdjusterインスタンスを生成し、そのインスタンスをwithメソッドの引数として渡します。
LocalDateTime dateTime = LocalDateTime.of(2025, 9, 9, 1, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M月d日");
System.out.println(dateTime.format(formatter));
//結果:9月9日
LocalDateTime dateTime1 = dateTime.with(
TemporalAdjusters.firstDayOfMonth());
System.out.println(dateTime1.format(formatter));
//結果:9月1日
LocalDateTime dateTime2 = dateTime.with(
TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
System.out.println(dateTime2.format(formatter));
//結果:9月7日
LocalDateTime dateTime3 = dateTime.with(
TemporalAdjusters.lastDayOfMonth() );
System.out.println(dateTime3.format(formatter));
//結果:9月30日
LocalDateTime dateTime4 = dateTime.with(
TemporalAdjusters.next(DayOfWeek.FRIDAY) );
System.out.println(dateTime4.format(formatter));
//結果:9月12日
LocalDateTime dateTime5 = dateTime.with(
TemporalAdjusters.previous(DayOfWeek.SUNDAY));
System.out.println(dateTime5.format(formatter));
//結果:9月7日
まとめ
- with〇〇メソッドで、特定の日時情報だけを変更した新しいインスタンスを生成できます
- plus〇〇メソッドやminus〇〇メソッドで、日時の加算・減算ができます。うるう年や月末日も自動で考慮されます
- isBeforeメソッド・isAfterメソッド・isEqualメソッドで、2つの日時インスタンスの前後関係や等価性を比較できます
- TemporalAdjusterを用いることで、「月末日」や「次の特定の曜日」など、複雑な条件の日付を算出できます
- LocalDateTimeは不変(イミュータブル)です。with〇〇メソッド・plus〇〇メソッド・minus〇〇メソッド・TemporalAdjusterを呼び出した際は、新しいインスタンスを生成してその参照を返します。元のインスタンスは変更されません
記事は以上です。
最後までお読みいただき、ありがとうございました。
参考情報一覧
この記事は以下の情報を参考にして執筆しました。
- [スッキリわかるJava入門 第4版]
- [パーフェクトJava 改訂3版]
- [プロになるJava]
- 20.2 Date and Time API(LocalDateTimeクラス、LocalDateクラス、LocalTimeクラス、Periodクラス、Durationクラス、ZonedDateTimeクラスなど)~Java Basic編 (最終更新 2023-11-05) (参照 2025-09-09)
- 公式ドキュメント (参照 2025-09-09)