Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
12
Help us understand the problem. What is going on with this article?
@ka_to

日付・時刻の形式チェック

More than 5 years have passed since last update.
isMatch_YYYYMMDD
日付が西暦4桁、月2桁、日2桁の形式かつ有効な日付かどうか
isMatch_HHMMSS
時刻が時2桁、分2桁、秒2桁の形式かつ有効な時刻かどうか
isMatchDateTime
上2つを確認する。日付と時刻は半角空白区切り
  • preg_matchを使用してチェックしている
  • $_exclusive_date_list変数で指定した形式の日付は有効な日付とする
/**
 * 日付チェックを除外する日付のリスト
 * @var array
 */
$_exclusive_date_list = array('00000000');

/**
 * 日付が西暦4桁、月2桁、日2桁の形式かどうか確認する
 * @param  string  $text         確認する文字列
 * @param  string  $delim        日付区切り文字。/を区切り文字とするときは'\/'とエスケープ文字を入れる
 * @param  boolean $errorIfEmpty 空文字列をエラーとするか TRUE:する FALSE:しない
 * @return boolean               有効な日付フォーマットかどうか TRUE:有効 FALSE:有効でない
 */
function isMatch_YYYYMMDD($text, $delim = '-', $errorIfEmpty = TRUE) {
    global $_exclusive_date_list;

    #空文字チェック
    if($text == ''){
        return !$errorIfEmpty;
    }

    #年 0000-9999 月 00-99 日 00-99
    $pattern = '/^([0-9]{4})' . $delim . '([0-9]{2})' . $delim . '([0-9]{2})$/';
    $matches = array();
    $match = isMatch($pattern, $text, $errorIfEmpty, $matches);
    if(!$match) {
        return FALSE;
    }

    #日付チェックを除外するかチェック
    if(in_array($matches[1] . $matches[2] . $matches[3], $_exclusive_date_list)) {
        return TRUE;
    }

    # 日付存在するかチェック
    if(!checkdate((int)$matches[2], (int)$matches[3], (int)$matches[1])) {
        return FALSE;
    }

    return TRUE;
}

/**
 * 時刻が時2桁、分2桁、秒2桁の形式かどうか確認する
 * @param  string  $text         確認する文字列
 * @param  string  $decimal      秒未満の桁数
 * @param  string  $delim        時刻区切り文字
 * @param  boolean $errorIfEmpty 空文字列をエラーとするか TRUE:する FALSE:しない
 * @return boolean               有効な時刻フォーマットかどうか TRUE:有効 FALSE:有効でない
 */
function isMatch_HHMMSS($text, $decimal = 0, $delim = ':', $errorIfEmpty = TRUE) {
    #空文字チェック
    if($text == ''){
        return !$errorIfEmpty;
    }

    //うるう秒はMySQLでは登録できないためフォーマットエラーとする。
    //対応する場合は下の正規表現を使用する
    //#時 00-23 分 00-59 秒 00-60
    //$pattern = '/^(0[0-9]{1}|1{1}[0-9]{1}|2{1}[0-3]{1})' . $delim . '(0[0-9]{1}|[1-5]{1}[0-9]{1})' . $delim . '(0[0-9]{1}|[1-5]{1}[0-9]{1}|60)';
    #時 00-23 分 00-59 秒 00-59
    $pattern = '/^(0[0-9]{1}|1{1}[0-9]{1}|2{1}[0-3]{1})' . $delim . '(0[0-9]{1}|[1-5]{1}[0-9]{1})' . $delim . '(0[0-9]{1}|[1-5]{1}[0-9]{1})';

    # 小数部があればパターンに追加
    if($decimal > 0) {
        $pattern = $pattern . sprintf('\.([0-9]{%d})', $decimal);
    }
    $pattern = $pattern . '$/';

    return isMatch($pattern, $text, $errorIfEmpty);
}

/**
 * 日時フォーマットかどうか確認する
 * 日付と時刻の間は半角空白で区切られていること
 * @param  string  $text         確認する文字列
 * @param  string  $decimal      秒未満の桁数
 * @param  boolean $errorIfEmpty 空文字列をエラーとするか TRUE:する FALSE:しない
 * @param  string  $date_delim   日付区切り文字。/を区切り文字とするときは'\/'とエスケープ文字を入れる
 * @param  string  $time_delim   時刻区切り文字
 * @return boolean               有効な日時フォーマットかどうか TRUE:有効 FALSE:有効でない
 */
function isMatchDateTime($text, $decimal = 0, $errorIfEmpty = TRUE, $date_delim = '-', $time_delim = ':') {
    #空文字チェック
    if($text == ''){
        return !$errorIfEmpty;
    }

    # 日付と時刻に分解
    $datetime = explode(' ', $text);
    if(count($datetime) < 2) {
        return FALSE;
    }

    # 日付
    if(!isMatch_YYYYMMDD($datetime[0], $date_delim)) {
        return FALSE;
    }

    # 時刻
    if(!isMatch_HHMMSS($datetime[1], $decimal, $time_delim)) {
        return FALSE;
    }

    return TRUE;
}

/**
 * 正規表現パターン検索
 * @param  string  $pattern      正規表現
 * @param  string  $text         確認する文字列
 * @param  boolean $errorIfEmpty 空文字列をエラーとするするか TRUE:する FALSE:しない
 * @return boolean               正規表現に合致するか TRUE:合致する FALSE:合致しない
 */
function isMatch($pattern, $text, $errorIfEmpty = TRUE, &$matches = array()) {
    #空文字チェック
    if($text == ''){
        return !$errorIfEmpty;
    }

    if(!preg_match($pattern, $text, $matches)) {
        return FALSE;
    } else {
        return TRUE;
    }
}

テストコード(全分岐網羅していない)

function testisMatch_YYYYMMDD($date, $exists = TRUE, $delim = '\/'){
    if(isMatch_YYYYMMDD($date, $delim, $exists))
        {echo '<font color="blue">'.$date.' 正しい日付</font><br/>';}
    else
        {echo '<font color="red">'.$date.' 不正な日付</font><br/>';}
}

function testisMatch_HHMMSS($time, $decimal = 0, $delim = ':'){
    if(isMatch_HHMMSS($time, $decimal, $delim))
        {echo '<font color="blue">'.$time.' 正しい時刻</font><br/>';}
    else
        {echo '<font color="red">'.$time.' 不正な時刻</font><br/>';}
}

echo '<h4>年が不正</h4>';
testisMatch_YYYYMMDD('/01/01'); #値なし
testisMatch_YYYYMMDD('200/01/01'); #桁不足

echo '<h4>月が不正</h4>';
testisMatch_YYYYMMDD('2012//01'); #値なし
testisMatch_YYYYMMDD('2012/1/01'); #桁不足
testisMatch_YYYYMMDD('2012/00/01'); #無効な月
testisMatch_YYYYMMDD('2012/13/01'); #無効な月

echo '<h4>日が不正</h4>';
testisMatch_YYYYMMDD('2012/01/'); #値なし
testisMatch_YYYYMMDD('2012/01/1'); #桁不足
testisMatch_YYYYMMDD('2012/01/00'); #無効な日
testisMatch_YYYYMMDD('2012/01/32'); #無効な日
testisMatch_YYYYMMDD('2014/02/29'); #無効な日

echo '<h4>0000/00/00はOK</h4>';
testisMatch_YYYYMMDD('0000/00/00');

echo '<h4>1000日チェック</h4>';
for($i = 0; $i <= 1000; $i++){
    $date = date('Y/m/d',mktime(0,0,0,date('n'),date('j')+$i,date('Y')-1));
    testisMatch_YYYYMMDD($date);
}

echo '<h4>年が不正(区切りなし)</h4>';
testisMatch_YYYYMMDD('0101', TRUE, ''); #値なし
testisMatch_YYYYMMDD('1000101', TRUE, ''); #桁不足

echo '<h4>全部ゼロはOK</h4>';
testisMatch_YYYYMMDD('00000000', TRUE, '');
echo '<h4>うるう年はOK</h4>';
testisMatch_YYYYMMDD('20120229', TRUE, ''); #2/29

echo '<h4>1000日チェック(区切りなし)</h4>';
for($i = 0; $i <= 1000; $i++){
    $date = date('Ymd',mktime(0,0,0,date('n'),date('j')+$i,date('Y')-1));
    testisMatch_YYYYMMDD($date, TRUE, '');
}

echo '<h4>時が不正</h4>';
testisMatch_HHMMSS(':59:59'); #値なし
testisMatch_HHMMSS('0:59:59'); #桁不足
testisMatch_HHMMSS('24:59:59'); #無効な時


echo '<h4>秒が不正</h4>';
testisMatch_HHMMSS('00:00:'); #値なし
testisMatch_HHMMSS('00:00:0'); #桁不足
testisMatch_HHMMSS('00:00:60'); #うるう秒はNG

echo '<h4>ミリ秒が不正</h4>';
testisMatch_HHMMSS('00:00:00.'); #値なし
testisMatch_HHMMSS('00:00:00.01'); #桁不足

echo '<h4>30時間チェック</h4>';
for($i = 0; $i <= 30; $i++){
    $time = date('H:i:s',mktime(0+$i,0,0,date('n'),date('j'),date('Y')));
    testisMatch_HHMMSS($time);
}
echo '<h4>100分チェック</h4>';
for($i = 0; $i <= 100; $i++){
    $time = date('H:i:s',mktime(0,0+$i,0,date('n'),date('j'),date('Y')));
    testisMatch_HHMMSS($time);
}
echo '<h4>100秒チェック</h4>';
for($i = 0; $i <= 100; $i++){
    $time = date('H:i:s',mktime(0,0,0+$i,date('n'),date('j'),date('Y')));
    testisMatch_HHMMSS($time);
}

echo '<h4>100ミリ秒チェック</h4>';
$millitime = date('H:i:s',mktime(0,0,0,date('n'),date('j'),date('Y')));
for($i = 0; $i <= 100; $i++){
    $time = date('H:i:s',mktime(0,0,0+$i,date('n'),date('j'),date('Y')));
    testisMatch_HHMMSS($millitime . '.' . sprintf('%03d', $i),3);
}

preg_match()正規表現チェッカー ver2.0

正規表現 時刻 の書式の判別 「preg_match()」

12
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ka_to

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
12
Help us understand the problem. What is going on with this article?