PHP strtotimeの落とし穴



PHPのstrtotimeは入力された文字列をUNIXタイムスタンプにしてくれる関数です。

この関数自体はとても便利なのですが様々な問題が多々あります。

日付のオーバーフロー

10000年以上の値を入力された場合、オーバーフローしてしまう。
<?php
// 正常
$date = '9999-12-31 23:59:59';
$date = date('Y-m-d H:i:s', strtotime($date));
echo "正常:".$date;

// オーバーフロー
$date = '10000-01-01 00:00:00';
$date = date('Y-m-d H:i:s', strtotime($date));
echo "オーバーフロー:".$date;
?>

実行結果
正常:9999-12-31 23:59:59
オーバーフロー:1970-01-01 00:00:00
上記の実行結果の用にオーバーフローされて1970年になってしまうので注意してください。

日時の自動計算

存在しない日時を入力した場合、入力された値から計算して自動的に日時を求めてしまいます。
<?php
// 自動計算
$date = '2014-06-31 24:00:00';
$date = date('Y-m-d H:i:s', strtotime($date));
echo "自動計算:".$date;
?>

実行結果
自動計算:2014-07-02 00:00:00
本来なら存在しない6月31日、24時を自動的に補完して7月2日と解釈してしまいます。

日付の加減算

こちらは前述の「日付の自動計算」のために起こっているようです。
<?php
// 加算
$date = '2014-07-31 00:00:00';
$date = date('Y-m-d H:i:s', strtotime($date.'+2 month'));
echo "加算:".$date;
?>

実行結果
加算:2014-10-01 00:00:00
本当なら9月の末尾になってほしいところを、9月31日→10月1日となってしまいます。
減算の時も同様のことが起きるので注意してください。
正しく前月、次月等を取りたい場合は日付を1日に指定して計算を行ったほうがいいです。
strtotimeはとても便利な関数ですが、どうも作りが甘く、下手に頼りすぎるとバグが発生する可能性が高いので注意してください。
というか、正しく出せないなら普通にエラーとしてfalseでも返して欲しい・・・


コメントを残す