Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】DateTimeInterface::diff()メソッドの使い方

diffメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

diffメソッドは、日付や時刻を表す2つのオブジェクト間の差を計算するメソッドです。このメソッドは、DateTimeInterfaceインターフェースを実装するオブジェクト、例えばDateTimeクラスやDateTimeImmutableクラスのインスタンスに対して呼び出されます。引数として別のDateTimeInterfaceオブジェクトを受け取り、呼び出し元のオブジェクトと引数で指定されたオブジェクトとの間の期間を計算します。計算結果は、年、月、日、時、分、秒といった各単位で期間を表すDateIntervalオブジェクトとして返されます。これにより、例えばイベントの開催期間や、ある時点から現在までの経過時間を正確に知ることができます。差が正の値になるか負の値になるかは、比較対象のオブジェクトが呼び出し元のオブジェクトより後か前かによって決定され、DateIntervalオブジェクトのinvertプロパティで確認できます。このメソッドは、時間管理やスケジュール調整など、日付と時刻の期間を扱う様々な場面で役立ちます。

構文(syntax)

1<?php
2$datetime1 = new DateTime('2023-01-01');
3$datetime2 = new DateTime('2023-01-31');
4$interval = $datetime1->diff($datetime2);
5?>

引数(parameters)

DateTimeInterface $targetObject, bool $absolute = false

  • DateTimeInterface $targetObject: 差分を計算する対象となるDateTimeInterfaceオブジェクト
  • bool $absolute = false: trueを指定すると、絶対差(常に正の値)を返します

戻り値(return)

DateInterval

DateTimeInterface::diff メソッドは、2つの DateTimeInterface オブジェクト間の差を DateInterval オブジェクトとして返します。DateInterval オブジェクトには、年、月、日、時、分、秒などの差分情報が含まれています。

サンプルコード

PHP: == と === でオブジェクト比較

1<?php
2
3/**
4 * PHPにおける「==」(ゆるい比較)と「===」(厳密な比較)の違いを、
5 * DateTimeオブジェクトとDateIntervalオブジェクトを例に示します。
6 *
7 * == (ゆるい比較): オペランドの値が等しい場合にtrueを返します。
8 *                  オブジェクトの場合、同じクラスで同じプロパティと値を持つ場合にtrueとなります。
9 * === (厳密な比較): オペランドの値と型が等しい場合にtrueを返します。
10 *                   オブジェクトの場合、同じインスタンス(つまり、メモリ上の同じオブジェクト)を参照している場合にのみtrueとなります。
11 */
12function demonstrateComparisonOperators(): void
13{
14    echo "--- DateTime オブジェクトの比較 ---\n";
15
16    // 同じ日時を表す異なるDateTimeインスタンスを作成
17    $dateTimeA = new DateTime('2023-01-01 10:00:00');
18    $dateTimeB = new DateTime('2023-01-01 10:00:00');
19    // dateTimeAと同じインスタンスへの参照を作成
20    $dateTimeC = $dateTimeA;
21    // 異なる日時を表すDateTimeインスタンスを作成
22    $dateTimeD = new DateTime('2023-01-01 11:00:00');
23
24    echo "dateTimeA: " . $dateTimeA->format('Y-m-d H:i:s') . "\n";
25    echo "dateTimeB: " . $dateTimeB->format('Y-m-d H:i:s') . "\n";
26    echo "dateTimeC: " . $dateTimeC->format('Y-m-d H:i:s') . " (dateTimeAと同じインスタンス)\n";
27    echo "dateTimeD: " . $dateTimeD->format('Y-m-d H:i:s') . "\n\n";
28
29    // dateTimeA と dateTimeB の比較 (同じ値だが異なるインスタンス)
30    echo "dateTimeA == dateTimeB (値の比較): " . (var_export($dateTimeA == $dateTimeB, true)) . "\n";
31    echo "dateTimeA === dateTimeB (値と型の比較/同じインスタンスか): " . (var_export($dateTimeA === $dateTimeB, true)) . "\n\n";
32    // 結果: == はtrue (値が同じ), === はfalse (インスタンスが異なる)
33
34    // dateTimeA と dateTimeC の比較 (同じ値で同じインスタンス)
35    echo "dateTimeA == dateTimeC (値の比較): " . (var_export($dateTimeA == $dateTimeC, true)) . "\n";
36    echo "dateTimeA === dateTimeC (値と型の比較/同じインスタンスか): " . (var_export($dateTimeA === $dateTimeC, true)) . "\n\n";
37    // 結果: == はtrue (値が同じ), === はtrue (インスタンスが同じ)
38
39    // dateTimeA と dateTimeD の比較 (異なる値)
40    echo "dateTimeA == dateTimeD (値の比較): " . (var_export($dateTimeA == $dateTimeD, true)) . "\n";
41    echo "dateTimeA === dateTimeD (値と型の比較/同じインスタンスか): " . (var_export($dateTimeA === $dateTimeD, true)) . "\n\n";
42    // 結果: == はfalse (値が異なる), === はfalse (インスタンスが異なる)
43
44    echo "--- DateInterval オブジェクトの比較 (DateTimeInterface::diff を使用) ---\n";
45
46    // dateTimeD と dateTimeA の時間差を計算
47    $interval1 = $dateTimeD->diff($dateTimeA); // 期間: -1時間
48    $interval2 = $dateTimeD->diff($dateTimeA); // interval1と同じ期間だが異なるインスタンス
49    $interval3 = $dateTimeA->diff($dateTimeD); // 期間: +1時間 (符号が異なる)
50    $interval4 = $dateTimeA->diff($dateTimeD, true); // 期間: +1時間 (absoluteがtrueなので常に正)
51
52    echo "interval1 (D->A): " . $interval1->format('%R%h hours') . "\n";
53    echo "interval2 (D->A): " . $interval2->format('%R%h hours') . "\n";
54    echo "interval3 (A->D): " . $interval3->format('%R%h hours') . "\n";
55    echo "interval4 (A->D, absolute): " . $interval4->format('%R%h hours') . "\n\n";
56
57    // interval1 と interval2 の比較 (同じ値だが異なるインスタンス)
58    echo "interval1 == interval2 (値の比較): " . (var_export($interval1 == $interval2, true)) . "\n";
59    echo "interval1 === interval2 (値と型の比較/同じインスタンスか): " . (var_export($interval1 === $interval2, true)) . "\n\n";
60    // 結果: == はtrue (値が同じ), === はfalse (インスタンスが異なる)
61
62    // interval1 と interval3 の比較 (異なる値 - 符号が異なるため)
63    echo "interval1 == interval3 (値の比較): " . (var_export($interval1 == $interval3, true)) . "\n";
64    echo "interval1 === interval3 (値と型の比較/同じインスタンスか): " . (var_export($interval1 === $interval3, true)) . "\n\n";
65    // 結果: == はfalse (値が異なる), === はfalse (インスタンスが異なる)
66
67    // interval3 と interval4 の比較 (同じ値 - どちらも+1時間)
68    echo "interval3 == interval4 (値の比較): " . (var_export($interval3 == $interval4, true)) . "\n";
69    echo "interval3 === interval4 (値と型の比較/同じインスタンスか): " . (var_export($interval3 === $interval4, true)) . "\n\n";
70    // 結果: == はtrue (値が同じ), === はfalse (インスタンスが異なる)
71}
72
73// 関数を実行
74demonstrateComparisonOperators();

PHPの==(ゆるい比較)と===(厳密な比較)は、オブジェクトの比較において異なる挙動を示します。==はオブジェクトのクラスとプロパティの値が等しい場合に真を返しますが、===は同じメモリ上のインスタンスを参照している場合にのみ真となります。

DateTimeInterface::diffメソッドは、あるDateTimeオブジェクトから別のDateTimeオブジェクトへの時間差を計算し、その期間をDateIntervalオブジェクトとして返します。このメソッドは第一引数に比較対象のDateTimeInterfaceオブジェクトを受け取ります。第二引数の$absolutetrueに設定すると、常に正の期間(絶対値)を返します。デフォルトはfalseで、時間差の方向に応じた符号付きの期間となります。

このサンプルコードでは、まず同じ日時を表す異なるDateTimeインスタンスや、同じインスタンスを参照する変数を比較し、=====の違いを明確に示しています。続いて、DateTimeInterface::diffメソッドを使って複数のDateIntervalオブジェクトを生成し、それらの比較を通じて、期間が同じでもインスタンスが異なる場合の=====の挙動、および$absolute引数の影響を具体的に解説しています。これにより、PHPにおけるオブジェクトの比較の原則と、日付・時間差の扱い方を理解できます。

PHPでオブジェクトを比較する際、== は「値」が等しいかを、=== は「同じインスタンス」かを厳密に比較します。同じ値を持つ異なるオブジェクトの場合、==true ですが、===false となるため注意が必要です。特に DateTimeInterface::diff メソッドは、呼び出すたびに新しい DateInterval オブジェクトを生成するため、たとえ同じ期間であっても === で比較すると常に false となります。状況に応じて適切な比較演算子を選びましょう。また、diff メソッドの absolute 引数を使用すると、時間差の符号を制御できます。

PHPで2つの日付の差を計算する

1<?php
2
3/**
4 * 2つの日付間の差を計算し、その結果を表示する関数です。
5 * DateTimeInterface::diff メソッドの基本的な使い方を、
6 * システムエンジニアを目指す初心者向けに分かりやすく解説します。
7 */
8function calculateDateDifference(): void
9{
10    // 比較対象となる最初の日付(DateTimeオブジェクト)を作成します。
11    // PHP 8では、DateTimeオブジェクトはDateTimeInterfaceを実装しています。
12    $startDate = new DateTime('2023-01-15 10:30:00');
13    echo "開始日: " . $startDate->format('Y-m-d H:i:s') . "\n";
14
15    // 比較対象となる二番目の日付(DateTimeオブジェクト)を作成します。
16    $endDate = new DateTime('2024-03-20 14:45:30');
17    echo "終了日: " . $endDate->format('Y-m-d H:i:s') . "\n";
18
19    // DateTimeInterface::diff メソッドを使用して、2つの日付間の差を計算します。
20    // このメソッドは DateInterval オブジェクトを返します。
21    // 第2引数 $absolute を true にすると、常に正の期間(絶対値)が返されます。
22    // デフォルトは false で、日付の順序によって期間の正負が変わります。
23    $interval = $startDate->diff($endDate);
24
25    echo "\n--- 日付の差 --- \n";
26
27    // DateInterval オブジェクトのプロパティを使って、期間の各要素にアクセスできます。
28    // y: 年, m: 月, d: 日, h: 時間, i: 分, s: 秒
29    echo "詳細な期間:\n";
30    echo "  年: " . $interval->y . "年\n";
31    echo "  月: " . $interval->m . "ヶ月\n";
32    echo "  日: " . $interval->d . "日\n";
33    echo "  時間: " . $interval->h . "時間\n";
34    echo "  分: " . $interval->i . "分\n";
35    echo "  秒: " . $interval->s . "秒\n";
36
37    // DateInterval::format() メソッドを使うと、期間をカスタムフォーマットで文字列化できます。
38    // 主なフォーマット指定子:
39    //   %R: 期間の符号 (+または-)
40    //   %a: 総日数 (絶対値)
41    //   %y: 年, %m: 月, %d: 日, %h: 時間, %i: 分, %s: 秒
42    echo "\nフォーマットされた期間:\n";
43    echo "  総日数: " . $interval->format('%R%a 日') . "\n"; // 期間の符号と総日数を表示
44    echo "  詳細な期間: " . $interval->format('%y年 %mヶ月 %d日 %h時間 %i分 %s秒') . "\n";
45
46    // diffメソッドの$absolute引数を使用する例 (常に正の期間を返す)
47    $absoluteInterval = $endDate->diff($startDate, true);
48    echo "\n--- 絶対値 (absolute = true) での期間 --- \n";
49    echo "  総日数: " . $absoluteInterval->format('%R%a 日') . "\n"; // 符号は常に +
50}
51
52// 関数を実行して日付の差を計算・表示します。
53calculateDateDifference();

PHPのDateTimeInterface::diffメソッドは、二つの日付間の期間(差)を計算するために使用されます。このサンプルコードでは、まず比較したい開始日と終了日をDateTimeオブジェクトとして作成します。DateTimeDateTimeInterfaceを実装しているため、diffメソッドを呼び出すことができます。

diffメソッドの最初の引数$targetObjectには、比較対象となる別のDateTimeInterfaceオブジェクトを渡します。二番目の引数$absoluteはオプションで、デフォルトはfalseです。falseの場合、開始日と終了日の前後関係によって期間が正または負のどちらかになりますが、trueを指定すると、常に正の期間(絶対値)が返されます。

このメソッドは、計算された期間を表すDateIntervalオブジェクトを戻り値として返します。DateIntervalオブジェクトには、y(年)、m(月)、d(日)、h(時間)、i(分)、s(秒)などのプロパティがあり、それぞれの期間要素に直接アクセスできます。また、DateInterval::format()メソッドを使用すると、総日数(%a)や特定の期間要素(%yなど)を自由に組み合わせて期間を文字列として整形できます。これにより、日付間の期間を柔軟に取得し、表示することが可能です。

DateTimeInterface::diffメソッドは、2つの日付オブジェクト間の差をDateIntervalオブジェクトとして返します。直接数値が返るわけではないため、返されたオブジェクトのプロパティ(年、月、日など)やformat()メソッドを使って期間情報を取得する必要がある点に注意しましょう。

第2引数$absolutefalse(デフォルト)にすると、比較する日付の順序によって期間の正負が変わります。常に正の期間が必要な場合はtrueを指定してください。

DateIntervalの各プロパティは期間の要素を示すため、厳密な総日数を求めたい場合はformat('%a')を利用するのが確実です。日付オブジェクトを作成する際には、タイムゾーンを明示的に指定することで、予期せぬ計算ミスを防ぐことができます。

関連コンテンツ