ごもちゃ箱BLOG

自作の PHP クラスライブラリ PEACH の開発日記です。

PHPで ISO8601 形式の時刻のバリデーション

以下の記事に触発されて, 拙作のライブラリを利用して ISO8601 形式の時刻 (正確には W3CDTF になりますが) のバリデーション関数を作ってみました. sota1235.hatenablog.com

下準備として Composer で PEACH2 ライブラリを準備します.

$ composer require trashtoy/peach2

以下がコード本体です.

<?php

use Peach\DT\W3cDatetimeFormat;
use Peach\DT\Timestamp;

require_once(__DIR__ . "/vendor/autoload.php");

$validateDate = function ($str) {
    try {
        // +09:00 を前提 (固定) として, 書式オブジェクト $f を作成します
        $f     = new W3cDatetimeFormat(-540); 
        // $f を使用して 文字列を Timestamp オブジェクトに変換します
        $t     = Timestamp::parse($str, $f);
        // $f を使用して Timestamp オブジェクトを文字列に再変換します
        $str2  = $t->format($f);
        // 元の文字列と再変換した文字列が同一であればバリデーション OK
        return ($str === $str2);
    } catch (InvalidArgumentException $e) {
        // parse に失敗した場合は NG
        return false;
    }
};

$testCases = [
    // 日付のみ指定のケース
    '2016-09-30',
    // 日付と時刻の間のTが抜けてるケース
    '2016-09-01 12:00:00+09:00',
    // タイムゾーンが抜けてるケース
    '2016-09-30T12:00:00',
    // 日付がでたらめなケース
    '2016-15-01T12:00:00+09:00', // 月
    '2016-09-31T12:00:00+09:00', // 日
    '2016-09-01T25:00:00+09:00', // 時
    '2016-09-01T12:61:00+09:00', // 分
    '2016-09-01T12:00:61+09:00', // 秒
    '2016-09-31T12:00:00+09:00', // 存在しない31日
    '2016-12-26T18:59:59+09:00', // OK
];

print_r(array_map($validateDate, $testCases));

以下が出力となります. 各テストケースを $validateDate に通した結果, 最後の文字列だけ true になりました.

Array
(
    [0] =>
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] =>
    [8] =>
    [9] => 1
)

タイムゾーンをハードコーディングで固定しているところがちょっとイケてないですね. (ちょっといじれば改善できそうですが)

今回のコードで使用されたクラスの API はこちらです.