DateIntervalとdiffで期間と日数を正しく扱う
DateIntervalとは、二つの日付の差や一定の期間を表すオブジェクトです。DateTimeのdiffで差分を取り出したり、addやsubで期間を足し引きするのに使います。
diffは二つの日付の差をDateIntervalで返す
二つの日付の差を求めたいとき、タイムスタンプの引き算で秒数を出して 86400 で割る、という力技をやりがちですが、DateTime の diff メソッドを使うほうが素直で安全ですね。差を DateInterval オブジェクトで返してくれます。
$from = new DateTimeImmutable('2026-07-01');
$to = new DateTimeImmutable('2026-07-22');
$diff = $from->diff($to);
echo $diff->days; // 21(総日数)
echo $diff->d; // 21(年月を除いた日部分)
ここで注意したいのが days と d の違いです。days は総日数、d は「年・月を差し引いた残りの日」なので、月をまたぐと値が変わります。日数計算では days を使うのが安全ですね。
年月日をまたぐと d と days がずれる
たとえば1か月と3日離れていると、d は 3、days は 34 前後になります。ここを取り違えると経過日数の集計がおかしくなるので、意図を確認しておきたいところです。
$a = new DateTimeImmutable('2026-01-15');
$b = new DateTimeImmutable('2026-02-18');
$diff = $a->diff($b);
echo $diff->m . 'か月' . $diff->d . '日'; // 1か月3日
echo $diff->days . '日'; // 34日
DateIntervalで期間を足し引きする
DateInterval は ISO8601 の期間表記で自分でも作れます。P が期間、T 以降が時刻部分です。add / sub と組み合わせて「30日後」「2時間前」のような計算に使えますね。Immutable なら結果を戻り値で受けます。
$now = new DateTimeImmutable('2026-07-22 10:00');
$after = $now->add(new DateInterval('P30D')); // 30日後
$before = $now->sub(new DateInterval('PT2H')); // 2時間前
echo $after->format('Y-m-d'); // 2026-08-21
echo $diff = $now->diff($after)->format('%a日'); // 30日
まとめ
期間の計算は自前の秒数演算よりも diff と DateInterval に任せたほうが、うるう年や月末の扱いを含めて安全だと思います。総日数なら days、年月を除いた端数なら d、という使い分けだけは取り違えないよう気をつけたいですね。format の %a も総日数を出せるので、表示のときに便利です。
よくある質問
Q. daysとdはどう違うのですか?
A. daysは二つの日付の総日数、dは年と月を差し引いた残りの日数です。経過日数を出したいときはdaysを使います。
Q. 期間を足し引きするにはどうしますか?
A. new DateInterval(‘P30D’)のようにISO8601表記で期間を作り、addやsubに渡します。Immutableなら結果は戻り値で受けます。
Q. うるう年や月末はdiffで正しく扱えますか?
A. diffとDateIntervalに任せれば内部で考慮されるので、自前の秒数計算よりも安全です。