PHPで日付を比較する9つの方法

JavaScriptを有効にしてください

まえがき

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, second0, 0, 0 にしないと、意図せず時間単位でのずれが発生する可能性がある。

6. date_create_from_format() を使う

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() は、日付文字列を解析し、連想配列として返す関数です。
この配列から yearmonthday の値を取得し、配列を比較することで日付の大小を判定できます。

[$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 クラスほどの柔軟性はない

8. format() を使ってISO 8601形式で比較

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 "無効な日付です";
}
1
無効な日付です
  • checkdate() は日付の妥当性を確認するだけで、比較はできない。
  • 例えば「2024年2月30日」は存在しないため false になるが、「2024年2月29日」はうるう年なので true になる。
  • strtotime()DateTime で無効な日付を渡すと予期しない結果になる可能性があるため、事前チェックに役立つ。

あとがき

PHPで日付を比較する方法は意外と多く、それぞれに特徴があります。strtotime() や DateTime クラスを使えば直感的に比較できますし、checkdate() を活用すれば無効な日付を防ぐことも可能です。用途によって適した手法を選ぶことで、より安全で効率的なコードを書くことができます。


スポンサーリンク

共有

もふもふ

プロフィール

著者
もふもふ
プログラマ。汎用系→ゲームエンジニア→Webエンジニア→QAエンジニア