2010年6月10日木曜日

PHPの DateIntervalクラスで経過日数を調べる場合の注意点

PHP5.3で新しく追加されたDateIntervalクラス。
一見便利そうだが、DateTimeクラスやstrToTime()のように日付等の繰り上がりを計算してくれないので注意が必要。
しかも、オブジェクトの生成方法により内部的なデータの持ち方が違う。


DateTimeクラスのdiff()(またはdate_diff())でDateIntervalオブジェクトを生成した場合、1ヶ月以上の日数は「月」に繰り上がる。
総日数は format('%a') で得られる。

$d1 = new DateTime('2010-01-01 01:01');
$d2 = new DateTime('2010-02-02 02:02');
$interval = $d2->diff($d1);

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で32日


でもDateIntervalクラスのコンストラクタで「1ヶ月と1日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') でも format('%a') でも得られない。
$interval = new DateInterval('P1M1D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


DateIntervalクラスのコンストラクタで「32日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') で得られる。format('%a') は使えない。
$interval = new DateInterval('P32D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 0ヶ月と32日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


format()する際には、DateIntervalオブジェクトをどうやって作ったかを意識する必要がある。

DateInterval::format()のマニュアルにも書いてあるとおり、これは仕様なのだろう。(月により1ヶ月の日数が違うため、コンストラクタでnヶ月と指定された場合にその総日数は不定のため。)

0 件のコメント:

ブログ アーカイブ

tags