まえがき
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() を活用すれば無効な日付を防ぐことも可能です。用途によって適した手法を選ぶことで、より安全で効率的なコードを書くことができます。