PHPのDateTimeクラスを使って日時の差分を取る時に注意すること

はじめに

とても今さら感のあるネタですが自分用にメモ。

プログラムで日付や時間を比較して何かを処理したい場合は多いはず。

PHPだとDateTimeクラスというのがあって、比較演算子==><などが使えます。

大小比較だけでなく、日時としての差分を取るためのDateTime::diff()メソッドも用意されていて、2つのDateTimeクラスの差分を表すDateIntervalクラスを返します。

DateInterval::format()メソッドを使って差分を確認するのですが、ちょっと癖があると思うので注意が必要です。

使い方は、下記の実験を見て貰えばわかるはず。

実験

翌日との比較

コード

<?php
$datetime1 = new DateTime('2015-11-20');
$datetime2 = new DateTime('2015-11-21');
$interval = $datetime1->diff($datetime2);

// %Rは符号を出力するオプション
echo $interval->format('%R%Y') . "\n"; // 年
echo $interval->format('%R%M') . "\n"; // 月
echo $interval->format('%R%D') . "\n"; // 日
echo $interval->format('%R%H') . "\n"; // 時
echo $interval->format('%R%I') . "\n"; // 分

結果

+00 // 年
+00 // 月
+01 // 日
+00 // 時 ?
+00 // 分 ??

翌月の同日との比較

コード

<?php
$datetime1 = new DateTime('2015-11-20 ');
$datetime2 = new DateTime('2015-12-20');
$interval = $datetime1->diff($datetime2);

echo $interval->format('%R%Y') . "\n"; // 年
echo $interval->format('%R%M') . "\n"; // 月
echo $interval->format('%R%D') . "\n"; // 日
echo $interval->format('%R%H') . "\n"; // 時
echo $interval->format('%R%I') . "\n"; // 分

結果

+00 // 年
+01 // 月
+00 // 日 ?
+00 // 時 ??
+00 // 分 ???

翌月の同日との比較その2

コード

<?php
$datetime1 = new DateTime('2015-11-20 ');
$datetime2 = new DateTime('2015-12-20');
$interval = $datetime1->diff($datetime2);

echo $interval->format('%R%Y') . "\n"; // 年
echo $interval->format('%R%M') . "\n"; // 月
echo $interval->format('%R%a') . "\n"; // 日 Dではなくaオプション(総日数)
echo $interval->format('%R%H') . "\n"; // 時
echo $interval->format('%R%I') . "\n"; // 分

結果

+00 // 年
+01 // 月
+30 // 日 やったぜ!
+00 // 時
+00 // 分

解説

要するに、DateTime::diff()で算出するのは、2つの日付の年月日時分秒のそれぞれの差分ということです。

上記の実験では%Hで時間の差を表示すると、どちらも時間が省略されているので0時と解釈されて、0時と0時の比較なので差は0時間です。

今日の0時と翌日の0時で比較した場合、差として24時間を期待したので、ちょっとはまりました。

唯一、日数のみ%aオプションというのが用意されていて総日数が取得できます。

全部にそういうオプション欲しい。

参考

http://php.net/manual/ja/datetime.diff.php