【PHP8.x】diffメソッドの使い方

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

作成日: 更新日:

基本的な使い方

diffメソッドは、2つのDateTimeオブジェクト間の時間的な差を計算し、その結果をDateIntervalオブジェクトとして返すメソッドです。PHP 8のDateTimeクラスに所属しており、プログラマーが日付や時刻の期間を正確に把握する際に非常に役立ちます。

このメソッドを使用すると、ある特定の日時から別の特定の日時までの間に、どれくらいの年、月、日、時、分、秒が存在するかを簡単に調べることができます。例えば、「会議の開始時刻から終了時刻までの経過時間」や、「ユーザー登録日から現在までの経過日数」などを計算するのに適しています。

diffメソッドは、比較対象となるDateTimeオブジェクトを引数として受け取ります。オプションで、差の絶対値を取得するかどうかを指定するブール値の引数も指定できます。絶対値が指定された場合、計算結果は常に正の値となり、どちらのDateTimeオブジェクトが先か後かに関わらず、純粋な期間だけが得られます。

計算された差は、DateIntervalオブジェクトとして返されます。このDateIntervalオブジェクトには、年(y)、月(m)、日(d)、時(h)、分(i)、秒(s)などのプロパティが含まれており、これらのプロパティを通じて個々の期間要素にアクセスできます。また、期間が負であるか(つまり、比較対象の日時が呼び出し元の日時より過去であるか)を示す情報も含まれます。

このメソッドを利用することで、日付計算に関する複雑なロジックを手動で実装する手間が省け、コードの保守性と正確性が向上します。システム開発において、イベント間の期間計算や年齢計算など、さまざまな場面で頻繁に活用される基本的な機能です。

構文(syntax)

1<?php
2
3$dateTime1 = new DateTime('2023-01-01');
4$dateTime2 = new DateTime('2023-01-31 10:00:00');
5
6// DateTimeオブジェクト間の差を計算します。
7// 第2引数はオプションで、trueを指定すると常に正の期間が返されます。
8$interval = $dateTime1->diff($dateTime2, false);
9
10// 計算された期間を表示します。
11echo $interval->format('%R%a days %H hours %I minutes');
12
13?>

引数(parameters)

DateTimeInterface $targetObject, bool $absolute = false

  • DateTimeInterface $targetObject: 比較対象となる DateTime オブジェクト
  • bool $absolute = false: true の場合、差を絶対値で返す

戻り値(return)

DateInterval

DateTimeオブジェクト同士の差分を表すDateIntervalオブジェクトを返します。このオブジェクトには、年、月、日、時、分、秒などの差分情報が含まれます。

サンプルコード

PHP DateTimeの==と===の違いをdiffで示す

1<?php
2
3/**
4 * PHPにおける == (緩やかな等価) と === (厳密な等価) の違いを、
5 * DateTimeオブジェクトを用いて実演するクラスです。
6 */
7class EqualityOperatorsDemo
8{
9    /**
10     * DateTimeオブジェクトに対する == と === の動作を比較し、
11     * DateTime::diff メソッドを関連するコンテキストとして使用します。
12     */
13    public static function demonstrateDateTimeEquality(): void
14    {
15        // --- ケース1: 同じ日時を表す異なるDateTimeインスタンスの比較 ---
16        // `new DateTime()` を2回呼び出すことで、2つの独立したオブジェクトが生成されます。
17        $dateTimeA = new DateTime('2023-10-27 15:30:00');
18        $dateTimeB = new DateTime('2023-10-27 15:30:00');
19
20        echo "--- ケース1: 同じ日時を表す異なるDateTimeインスタンス ---\n";
21        echo "DateTimeA: " . $dateTimeA->format('Y-m-d H:i:s.u') . "\n";
22        echo "DateTimeB: " . $dateTimeB->format('Y-m-d H:i:s.u') . "\n";
23
24        // == (緩やかな等価): オブジェクトが同じクラスに属し、同じプロパティ値を持つ場合にtrue。
25        // DateTimeオブジェクトの場合、同じ日時を表していればtrueになります。
26        if ($dateTimeA == $dateTimeB) {
27            echo "  \$dateTimeA == \$dateTimeB は TRUE です (両者は同じ日時を表しています)。\n";
28        } else {
29            echo "  \$dateTimeA == \$dateTimeB は FALSE です。\n";
30        }
31
32        // === (厳密な等価): 変数が全く同じオブジェクトインスタンスを参照している場合にtrue。
33        // この場合、2つの独立したオブジェクトなのでfalseになります。
34        if ($dateTimeA === $dateTimeB) {
35            echo "  \$dateTimeA === \$dateTimeB は TRUE です (両者は全く同じインスタンスです)。\n";
36        } else {
37            echo "  \$dateTimeA === \$dateTimeB は FALSE です (両者は異なるインスタンスです)。\n";
38        }
39
40        // DateTime::diff を使用して、2つのDateTimeオブジェクト間の時間差を計算します。
41        // 同じ日時を表す場合、差は0となります。
42        $difference = $dateTimeA->diff($dateTimeB);
43        echo "  \$dateTimeA と \$dateTimeB の差 (DateTime::diff): " . $difference->format('%R%a days %H hours %I minutes %S seconds') . "\n";
44        if ($difference->days === 0 && $difference->h === 0 && $difference->i === 0 && $difference->s === 0) {
45            echo "  diffの結果は、両者が同じ時点であることを示しています。\n";
46        }
47        echo "\n";
48
49
50        // --- ケース2: 既存のDateTimeインスタンスへの参照を持つ変数の比較 ---
51        // $dateTimeC は $dateTimeA と全く同じオブジェクトインスタンスを参照します。
52        $dateTimeC = $dateTimeA;
53
54        echo "--- ケース2: 同じDateTimeインスタンスへの参照を持つ変数 ---\n";
55        echo "DateTimeA: " . $dateTimeA->format('Y-m-d H:i:s.u') . "\n";
56        echo "DateTimeC (DateTimeAへの参照): " . $dateTimeC->format('Y-m-d H:i:s.u') . "\n";
57
58        // == (緩やかな等価): 同じ日時を表すため、trueになります。
59        if ($dateTimeA == $dateTimeC) {
60            echo "  \$dateTimeA == \$dateTimeC は TRUE です (両者は同じ日時を表しています)。\n";
61        } else {
62            echo "  \$dateTimeA == \$dateTimeC は FALSE です。\n";
63        }
64
65        // === (厳密な等価): 両者は全く同じオブジェクトインスタンスを参照しているため、trueになります。
66        if ($dateTimeA === $dateTimeC) {
67            echo "  \$dateTimeA === \$dateTimeC は TRUE です (両者は全く同じインスタンスです)。\n";
68        } else {
69            echo "  \$dateTimeA === \$dateTimeC は FALSE です。\n";
70        }
71        echo "\n";
72    }
73}
74
75// デモンストレーションを実行します
76EqualityOperatorsDemo::demonstrateDateTimeEquality();
77

PHPにおける==(緩やかな等価)と===(厳密な等価)演算子は、変数の比較に用いられ、DateTimeオブジェクトの比較ではその違いが明確になります。==は、オブジェクトが同じクラスに属し、同じプロパティ値を持つ場合にtrueを返します。そのため、異なるインスタンスであっても、同じ日時を表すDateTimeオブジェクト同士であればtrueとなります。対して===は、変数が全く同じオブジェクトインスタンスを参照している場合にのみtrueを返します。

サンプルコードでは、まず同じ日時を表す二つの異なるDateTimeインスタンスを生成しています。この場合、日時が等しいため==trueですが、インスタンスが異なるため===falseとなります。 DateTime::diffメソッドは、二つのDateTimeInterfaceオブジェクト間の時間差を計算し、その結果をDateIntervalオブジェクトとして返します。引数$targetObjectには比較対象のDateTimeオブジェクトを渡し、$absolutetrueにすると差を常に正の値で得られます。同じ日時を表すオブジェクト同士のdiffは、期間がゼロのDateIntervalを返します。

次に、既存のDateTimeインスタンスへの参照を持つ変数を比較しています。この場合、両変数は全く同じインスタンスを参照しているため、=====の両方がtrueとなります。このように、==は値の等価性、===はインスタンスの同一性を比較する際に使用します。

PHPのオブジェクト比較では、==は「内容が同じか」を、===は「全く同じインスタンスか」を判定します。DateTimeオブジェクトの場合、==は「同じ日時を表しているか」を確認し、===は「同じオブジェクトインスタンスを参照しているか」を確認します。したがって、new DateTime()を複数回呼び出すと、たとえ同じ日時を設定しても、===ではfalse==ではtrueとなる点に注意が必要です。日時間の厳密な差分を求めたい場合は、DateTime::diffメソッドを利用し、戻り値のDateIntervalオブジェクトのプロパティで詳細を確認するようにしてください。

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

1<?php
2
3/**
4 * 2つの日付間の差を計算し、表示します。
5 * DateTime::diff メソッドを使用して、日付と時刻の差を求めます。
6 *
7 * @param DateTimeInterface $date1 比較する最初のDateTimeオブジェクト。
8 * @param DateTimeInterface $date2 比較する2番目のDateTimeオブジェクト。
9 * @return void 結果をコンソールに出力します。
10 */
11function displayDateDifference(DateTimeInterface $date1, DateTimeInterface $date2): void
12{
13    echo "--- 日付の差を計算 ---" . PHP_EOL;
14    echo "日付1: " . $date1->format('Y-m-d H:i:s') . PHP_EOL;
15    echo "日付2: " . $date2->format('Y-m-d H:i:s') . PHP_EOL;
16
17    // 2つの日付間の差を計算します。
18    // diffメソッドはDateIntervalオブジェクトを返します。
19    // 第二引数 $absolute はデフォルトで false です。
20    // date2がdate1より過去の場合に「-」、未来の場合に「+」の符号が付きます。
21    $interval = $date1->diff($date2);
22
23    // DateIntervalオブジェクトを人間が読みやすい文字列にフォーマットします。
24    // %R: 差の符号 (+ または -)
25    // %y: 年、%m: 月、%d: 日、%h: 時間、%i: 分、%s: 秒
26    echo "差 (年, 月, 日, 時刻): " . $interval->format('%R%y年 %mヶ月 %d日 %h時間 %i分 %s秒') . PHP_EOL;
27
28    // 2つの日付間の合計日数 (常に正の値) を取得するには、DateIntervalの 'days' プロパティを使用します。
29    echo "日付間の合計日数 (絶対値): " . $interval->days . PHP_EOL;
30
31    // もし、常に正の差が必要な場合、diffメソッドの第二引数に true を渡します。
32    $absoluteInterval = $date1->diff($date2, true);
33    echo "差 (常に正、年月日の詳細): " . $absoluteInterval->format('%y年 %mヶ月 %d日') . PHP_EOL;
34
35    echo PHP_EOL; // 例の間を区切るための改行
36}
37
38// --- サンプル使用例 ---
39
40// 例1: 未来のデータとの差
41$dateA = new DateTime('2023-01-15 10:00:00');
42$dateB = new DateTime('2023-03-20 15:30:45');
43displayDateDifference($dateA, $dateB);
44
45// 例2: 過去のデータとの差
46$dateX = new DateTime('2024-05-10 12:00:00');
47$dateY = new DateTime('2023-11-25 08:30:00');
48displayDateDifference($dateX, $dateY);
49
50// 例3: 全く同じ日付の場合 (差は0になる)
51$dateP = new DateTime('2023-07-01 09:00:00');
52$dateQ = new DateTime('2023-07-01 09:00:00');
53displayDateDifference($dateP, $dateQ);
54

PHPのDateTimeクラスのdiffメソッドは、二つの日付と時刻の間の差を計算します。第一引数に比較対象のDateTimeInterfaceオブジェクトを指定します。

このメソッドは、差の詳細情報を保持するDateIntervalオブジェクトを返します。返されたオブジェクトは、format()メソッドを使うことで「%y年 %mヶ月」のように人間が読みやすい形式で表示できます。年、月、日、時間、分、秒ごとの差を取得することが可能です。

第二引数$absoluteは、差を常に正の値として扱うかを指定します。デフォルトのfalseでは、日付の順序によって正負の符号(例えば「-1年」)が付きます。trueを指定すると、常に絶対値で差が返されます。また、DateIntervalオブジェクトのdaysプロパティからは、日付間の合計日数を常に正の整数で取得できます。このメソッドとDateIntervalオブジェクトを活用することで、日付計算を正確かつ柔軟に扱えます。

PHPのDateTime::diffメソッドは、2つの日付間の差をDateIntervalオブジェクトとして返します。このオブジェクトは直接数値ではないため、結果はformat()メソッドで「年、月、日、時間」などの詳細を、またはdaysプロパティで「合計日数」を取得して利用します。第二引数$absoluteのデフォルト値はfalseで、$date1から$date2への方向によって差に正負の符号が付きます。常に正の差が必要な場合は$absolutetrueを指定してください。特に$interval->daysは、$absoluteの設定に関わらず、日付間の合計日数を常に正の整数で返しますので、この違いを理解して使い分けることが重要です。

【PHP8.x】diffメソッドの使い方 | いっしー@Webエンジニア