日付API

このレッスンを終えると、LocalDate が不変であることによる罠と、Period の読み方を説明できるようになります。

まず予測してください

次のコードは何を表示するでしょうか。

LocalDate d = LocalDate.of(2026, 8, 1); d.plusDays(30); System.out.println(d);

答えは 2026-08-01 です。30 日進んでいません。ここが日付 API のいちばんの引っ掛けどころです。

日付クラスは全部が不変

LocalDateLocalTimeLocalDateTime も不変です。plusDaysminusMonthswithDayOfMonth は、新しいオブジェクトを作って返すだけで、呼び出した相手を書き換えません。だから戻り値を受け取らないと何も起きません。String の toUpperCase と同じ考え方です。

正しくは次のように書きます。

LocalDate moved = d.plusDays(30);

試験では、戻り値を捨てた行をさりげなく混ぜて「出力は」と聞いてきます。行の先頭が変数への代入になっているかを必ず見てください。

コンストラクタは使えない

new LocalDate(2026, 8, 1) はコンパイルエラーです。コンストラクタが公開されていないので、LocalDate.ofLocalDate.parse といった static メソッドで作ります。of の月は 1 から 12 で、昔の Calendar のような 0 始まりではありません。範囲外の月や日を渡すと DateTimeException が実行時に飛びます。

toString2026-08-01 の形になります。ゼロ埋めされる点も出力を答える問題で効いてきます。

Period は年月日に分かれる

Period.between(開始, 終了) は、2つの日付の差を年と月と日に分けて持ちます。getMonths は「差のうちの月の部分」であって、通算の月数ではありません。8 月 1 日から 9 月 15 日までなら、getMonths は 1 で getDays は 14 です。45 という数字はどこにも出てきません。

通算の日数がほしいときは ChronoUnit.DAYS.between を使います。Period の getDays と混同させる問題が繰り返し出ているので、分けて覚えてください。

要件

  1. 起点は LocalDate.of(2026, 8, 1) とする。実行するたびに変わる値は使わない
  2. 起点から days 日進めた日付を作る。起点そのものは変えない
  3. 起点から進めた日付までの Period を求める
  4. 起点、進めた日付、Period の月、Period の日をこの順にスラッシュでつないで返す

入出力例

shift(30)"2026-08-01/2026-08-31/0/30" shift(45)"2026-08-01/2026-09-15/1/14" shift(10)"2026-08-01/2026-08-11/0/10"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

日付API

⌘S で保存