PHPのDateTime型を用いて日時の妥当性を調べる
備忘録として小ネタです。日時といったらよく
yyyy-mm-dd hh:mm:ss
の文字列として表現されますが、例えば今日の日付も「08日」と表記されるか「8日」と表記されるかでは機械的には別に解釈されてしまいます。csvファイルをExcelで開いて日時を記載する欄に日付を書くと、頭の0はなくなり「8日」に整形されます。
厳密に評価してddの形ではないのでダメとしてもいいのですが、セルの設定まで変えてyyyy-mm-dd hh:mm:ssの形に記載させるのは不毛な気がしてます。そこでいい方法はないか。妥当性を調べる意味でも「yyyy-mm-dd」と「hh:mm:ss」を分けて前者は「-」で文字列を分割して、checkdate()を使い後者は正規表現等で評価する等よく見かけますが、とりあえず文字列をそのままDateTime型に当てはめてみる方法で調べることができたりします。PHP.netのDateTime::getLastErrorsに載っている下記のサンプルコードに入れてみましょう。
サンプルコード
try{
$date = new DateTime($str);
}catch (Exception $e) {
print_r($e->getLastErrors()); // とりあえず表示
}
サンプルデータ($str=渡す文字列、#=>結果)
$str1 = "0000"; // #=> Failed to parse time string ( throw Exception)
$str2 = "0000-00-00 00:00:00"; // #=> The parsed date was invalid (warnings)
$str3 = "2008-02-29 00:00:00"; // #=> 正常終了
$str4 = "2009-02-29 00:00:00"; // #=> The parsed date was invalid (warnings)
上記で見た通り”とりあえずDateTimeに入れてみる”だけで妥当性をチェックしてくれます。しかし、注意せねばならないものが太字で表した二つのケース。
両方とも「日付としては間違っている($str4の2009年は閏年ではないためおかしい)にも関わらず、warningになってしまうため例外は発行されません。例え例外が発行されずともDateTime::getLastErrors()を見る必要があります。ErrorよりWarningの方が重度だったりします。
厳密な日付チェックは元々用途として想定されていないのかもしれませんが使えます。