まえがき
PHPで日付を比較する場面は多く、たとえば「過去の日付かどうかを判定する」「2つの日付の差を計算する」「特定の期間内にあるかチェックする」など、さまざまな用途があります。しかし、一口に「日付を比較する」と言っても、その方法は1つではありません。
本記事では、PHPで日付を比較する方法を紹介し、それぞれの使用方法と注意点について解説します。状況に応じて適切な方法を選べるようになることで、コードの可読性や保守性が向上します。ぜひ参考にしてみてください。
1. strtotime() を使う
strtotime() は、指定した日付文字列を UNIX タイムスタンプ(秒数)に変換する関数です。
比較演算子 (<, >, == など) を使って、日付の大小を比較できます。
| 1
2
3
4
5
6
7
8
 | <?php
$date1 = strtotime("2024-03-01");
$date2 = strtotime("2024-03-05");
echo "$date1 < $date2<br>";
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
| 1
2
 | 1709251200 < 1709596800
date1 は date2 よりも前の日付です
 | 
- strtotime()は文字列を解析するため、書式が不適切だと- falseを返すことがあります。
- タイムゾーンの影響を受ける可能性があるので、date_default_timezone_set()を適切に設定しておきましょう。
2. DateTime クラスを使う
DateTime クラスを利用すると、オブジェクト指向的に日付を扱うことができます。
new DateTime() でオブジェクトを作成し、比較演算子 (<, >, ==) を使って比較できます。
| 1
2
3
4
5
6
7
8
9
 | <?php
$date1 = new DateTime("2024-03-01");
$date2 = new DateTime("2024-03-05");
print_r($date1);
print_r($date2);
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | DateTime Object
(
    [date] => 2024-03-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
DateTime Object
(
    [date] => 2024-03-05 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
date1 は date2 よりも前の日付です
 | 
- DateTimeオブジェクトを使う場合、- DateTimeImmutableも考慮するとよいでしょう。
 (- DateTimeは変更可能ですが、- DateTimeImmutableは変更不可)
- DateTimeは内部でタイムゾーンを考慮するため、異なるタイムゾーンの比較を行う場合は- setTimezone()を明示的に設定するとよいです。
- DateTimeクラスは PHP 5.2 以降で使用可能。
3. diff() メソッドを使う
DateTime::diff() を使うと、2つの日付の差を取得できます。
返り値は DateInterval オブジェクトで、days プロパティを使うことで日数の差を取得できます。
invert プロパティを使うと、どちらが先かを判定できます(invert == 1 なら負の差)。
| $diff->invertの値 | 意味 | 
|---|
| 0 | $date1は$date2より前 | 
| 1 | $date1は$date2より後 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | <?php
$date1 = new DateTime("2024-03-01");
$date2 = new DateTime("2024-03-05");
$diff = $date1->diff($date2);
echo "日数の差: " . $diff->days . " 日<br>";
if ($diff->invert) {
    echo "date1 は date2 より後の日付です";
} else {
    echo "date1 は date2 より前の日付です";
}
 | 
| 1
2
 | 日数の差: 4 日
date1 は date2 より前の日付です
 | 
- diff()の結果は- DateIntervalオブジェクトなので、比較する場合は- ->daysを使う必要があります。
- 時間部分も含めた比較をする場合、時刻の影響を考慮する必要があります。
4. date() を使って数値比較
date("Ymd") を使って YYYYMMDD 形式の数値を作成し、数値として比較する方法です。
strtotime() を併用すると、文字列のまま処理するよりも精度が高くなります。
| 1
2
3
4
5
6
7
8
 | <?php
$date1 = (int) date("Ymd", strtotime("2024-03-01"));
$date2 = (int) date("Ymd", strtotime("2024-03-05"));
echo "$date1 < $date2<br>";
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
| 1
2
 | 20240301 < 20240305
date1 は date2 よりも前の日付です
 | 
- date("Ymd")は- int型に変換してから比較することで、文字列の辞書順比較を回避できます。
- ただし、この方法では 時刻情報は無視される ので、時間単位での比較はできません。
- 年月日のみで比較する場合には問題ないが、時刻まで含めた比較をしたい場合は strtotime()やDateTimeを使う方が適切。
5. mktime() を使う
mktime(hour, minute, second, month, day, year) を使って UNIX タイムスタンプを生成し、
数値として比較する方法です。
| 1
2
3
4
5
6
7
8
 | <?php
$date1 = mktime(0, 0, 0, 3, 1, 2024);
$date2 = mktime(0, 0, 0, 3, 5, 2024);
echo "$date1 < $date2<br>";
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
| 1
2
 | 1709251200 < 1709596800
date1 は date2 よりも前の日付です
 | 
- mktime()の引数は- (hour, minute, second, month, day, year)の順なので、間違えないように注意。
- strtotime()と違い、日付文字列の解析は行わないため、手動で- mktime()の引数を設定する必要がある。
- mktime()の- hour, minute, secondを- 0, 0, 0にしないと、意図せず時間単位でのずれが発生する可能性がある。
date_create_from_format("フォーマット", "日付文字列") を使うと、特定のフォーマットで DateTime オブジェクトを作成できます。
例えば "01/03/2024" のような d/m/Y 形式の日付でも、正しく DateTime に変換できます。
通常の new DateTime() よりも、フォーマットが決まっている場合に便利です。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 | <?php
$date1 = date_create_from_format("d/m/Y H:i:s", "01/03/2024 00:00:00");
$date2 = date_create_from_format("d/m/Y H:i:s", "05/03/2024 00:00:00");
print_r($date1);
print_r($date2);
if ($date1 === false || $date2 === false) {
    echo "日付のフォーマットが正しくありません";
} else {
    if ($date1 < $date2) {
        echo "date1 は date2 より前の日付です";
    } else {
        echo "date1 は date2 より後の日付です";
    }
}
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | DateTime Object
(
    [date] => 2024-03-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
DateTime Object
(
    [date] => 2024-03-05 00:00:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
date1 は date2 より前の日付です
 | 
- 指定したフォーマットと異なる形式の日付を渡すと、エラーにならずに falseを返す可能性があるため、事前チェックが必要。
- date_create_from_format()の戻り値が- falseかどうかを- if ($date1 === false)でチェックすると安全。
- date_create_from_format()は時間を省略すると現在時刻で補完されるため、時間の影響を避けたい場合は 明示的に 00:00:00 を指定する
7. date_parse() を使って比較
date_parse() は、日付文字列を解析し、連想配列として返す関数です。
この配列から year、month、day の値を取得し、配列を比較することで日付の大小を判定できます。
[$date1['year'], $date1['month'], $date1['day']] の形式にすることで、連想配列の値を YYYYMMDD の数値順に比較できます。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 | <?php
$date1 = date_parse("2024-03-01");
$date2 = date_parse("2024-03-05");
print_r($date1);
print_r($date2);
if ([$date1['year'], $date1['month'], $date1['day']] < [$date2['year'], $date2['month'], $date2['day']]) {
    echo "date1 は date2 より前の日付です";
} else {
    echo "date1 は date2 より後の日付です";
}
?>
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 | Array
(
    [year] => 2024
    [month] => 3
    [day] => 1
    [hour] => 
    [minute] => 
    [second] => 
    [fraction] => 
    [warning_count] => 0
    [warnings] => Array
        (
        )
    [error_count] => 0
    [errors] => Array
        (
        )
    [is_localtime] => 
)
Array
(
    [year] => 2024
    [month] => 3
    [day] => 5
    [hour] => 
    [minute] => 
    [second] => 
    [fraction] => 
    [warning_count] => 0
    [warnings] => Array
        (
        )
    [error_count] => 0
    [errors] => Array
        (
        )
    [is_localtime] => 
)
date1 は date2 より前の日付です
 | 
- date_parse()はエラーチェックをしないので、無効な日付 (- 2024-02-30など) も解析してしまう
- 時間情報も含まれるが、解析時に 0が補完されるため、時刻付きの比較には向かない
- DateTimeクラスほどの柔軟性はない
DateTime::format("c") を使うと、ISO 8601 (例: "2024-03-01T00:00:00+00:00") に変換される。
このフォーマットは、文字列として比較しても日付の順序が正しく反映される。
| 1
2
3
4
5
6
7
8
 | <?php
$date1 = (new DateTime("2024-03-01"))->format("c");
$date2 = (new DateTime("2024-03-05"))->format("c");
echo "$date1 < $date2<br>";
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
| 1
2
 | 2024-03-01T00:00:00+00:00 < 2024-03-05T00:00:00+00:00
date1 は date2 よりも前の日付です
 | 
- format("c")の出力は- YYYY-MM-DDTHH:MM:SS+00:00形式なので、タイムゾーンの影響を受ける。
- 文字列比較 ($date1 < $date2) を行うため、数値比較 (getTimestamp()) よりも若干処理が遅くなる可能性がある。
- 時刻情報も含まれるため、日単位の比較では意図しない結果になる場合がある。
9. getTimestamp() を使う
DateTime::getTimestamp() を使うと、日時を UNIX タイムスタンプ(秒数)に変換できる。
タイムスタンプ同士を数値比較 (<, >, ==) することで、シンプルに大小判定が可能。
| 1
2
3
4
5
6
7
8
 | <?php
$date1 = (new DateTime("2024-03-01"))->getTimestamp();
$date2 = (new DateTime("2024-03-05"))->getTimestamp();
echo "$date1 < $date2<br>";
if ($date1 < $date2) {
    echo "date1 は date2 よりも前の日付です";
}
 | 
| 1
2
 | 1709251200 < 1709596800
date1 は date2 よりも前の日付です
 | 
- getTimestamp()は秒単位の精度なので、時刻情報を含めた比較ができる。
- strtotime()と異なり、明示的に- DateTimeオブジェクトを作成する必要がある。
- タイムゾーンの影響を受ける可能性があるため、setTimezone()で統一しておくとよい。
番外編. checkdate() を使って比較前に検証
これまでに紹介してきた方法で比較する前にcheckdate()関数を使用して事前にチェックするとより効果的です。
checkdate() は、指定された年月日が有効な日付かどうかを判定する関数です。
月の範囲 (1~12) や、その月の日数 (2月なら28または29日) を考慮してチェックします。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
 | <?php
$year = 2024;
$month = 2;
$day = 30;
if (checkdate($month, $day, $year)) {
    echo "有効な日付です";
} else {
    echo "無効な日付です";
}
 | 
- checkdate()は日付の妥当性を確認するだけで、比較はできない。
- 例えば「2024年2月30日」は存在しないため falseになるが、「2024年2月29日」はうるう年なのでtrueになる。
- strtotime()や- DateTimeで無効な日付を渡すと予期しない結果になる可能性があるため、事前チェックに役立つ。
あとがき
PHPで日付を比較する方法は意外と多く、それぞれに特徴があります。strtotime() や DateTime クラスを使えば直感的に比較できますし、checkdate() を活用すれば無効な日付を防ぐことも可能です。用途によって適した手法を選ぶことで、より安全で効率的なコードを書くことができます。