Duration で時間差を計算
日数の差を引き算で出すと、月をまたいだ瞬間に合わなくなる
「登録から 30 日たった人にメールを送る」「予約日まであと何日か表示する」。日付の差を数える処理は、業務アプリでいくらでも出てきます。ところが 日 の値どうしを引き算する方法は、同じ月の中でしか通用しません。月をまたげば月の長さを足す必要があり、年をまたげばうるう年かどうかまで自分で判定するはめになります。
java.time には、2 点間の差を単位ごとに数えてくれる ChronoUnit があります。DAYS HOURS MINUTES MONTHS YEARS といった単位を選び、between に始点と終点を渡すだけです。
Java
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class Demo {
public static void main(String[] args) {
LocalDate open = LocalDate.of(2026, 4, 1);
LocalDate deadline = LocalDate.of(2026, 5, 19);
long days = ChronoUnit.DAYS.between(open, deadline);
System.out.println(days); // 48
}
}4 月が 30 日までであることも、月がまたがっていることも、こちら側では一切考えていません。うるう年をまたいでも同じように正しい値が返ります。
3 時間半のはずが 3 と返ってくる
between は「その単位が何回まるごと入るか」を数えるので、端数は切り捨てられます。9 時から 12 時 30 分までを HOURS で聞くと 3 です。
Java
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
LocalDateTime start = LocalDateTime.of(2026, 4, 1, 9, 0);
LocalDateTime end = LocalDateTime.of(2026, 4, 1, 12, 30);
System.out.println(ChronoUnit.MINUTES.between(start, end)); // 210
System.out.println(ChronoUnit.HOURS.between(start, end)); // 33.5 が欲しいわけではなく「何時間何分か」を知りたいのなら、細かい単位で取ってから自分で組み立てます。上の例なら 210 分を 60 で割って商と余りを出せば、3 時間 30 分になります。
引数を入れ替えると符号が反転する
between(start, end) が返すのは end から start を引いた値です。つまり start のほうが未来なら結果は負になります。
Java
LocalDate open = LocalDate.of(2026, 4, 1);
LocalDate deadline = LocalDate.of(2026, 5, 19);
System.out.println(ChronoUnit.DAYS.between(deadline, open)); // -48これは不具合ではなく仕様です。「締め切りを過ぎているかどうか」を判定したいなら符号がそのまま答えになりますし、単に日数だけ知りたいなら Math.abs で絶対値を取ります。過去か未来かの情報を捨てる前に、本当に捨てていいのか一度考えてください。
betweenの戻り値はlongです。intの変数に入れたいときは(int)で明示的にキャストします。intは約 21 億まで扱えて、日数に直すと 580 万年を超えるので、日付の差であふれる心配はまずありません。
やってみよう
Solution.daysBetween(int year1, int month1, int day1, int year2, int month2, int day2) を完成させます。
import java.time.LocalDate;とimport java.time.temporal.ChronoUnit;を書く- 受け取った 6 つの数値から
LocalDateを 2 つ作る - 日数の差を求め、
intに変換してreturnする
daysBetween(2026, 5, 1, 2026, 5, 19) は 18、daysBetween(2026, 5, 19, 2026, 5, 1) は -18 です。順番を逆にしたときに負の値が返ることまで確認されるので、絶対値を取ってはいけません。
要件
- ファイル先頭で
import java.time.LocalDate;とimport java.time.temporal.ChronoUnit;を書くこと LocalDate.of(year, month, day)を 2 回呼んで 2 つのLocalDateを作ることChronoUnit.DAYS.between(d1, d2)の戻り値 (long) を(int)でキャストして返すこと
入出力例
daysBetween(2026, 5, 1, 2026, 5, 19) → 18
daysBetween(2024, 1, 1, 2024, 12, 31) → 365
daysBetween(2026, 5, 19, 2026, 5, 19) → 0
daysBetween(2026, 5, 19, 2026, 5, 1) → -18
daysBetween(2025, 12, 31, 2026, 1, 1) → 1