読者です 読者をやめる 読者になる 読者になる

正規表現で日付抽出

正規表現で日付抽出をするために書いたphpのコードです。
dateExtraction関数の引数に文字列を入れると、
文字列の先頭に日付情報があればそれが "Y-m-d" の形式で返されます。
「今日」、「先週の金曜日」、「○日前」、「○回後の○曜日」などの形式にも
対応しています。

<?php
function str_Y($nmb){
    return date("Y年",strtotime("".$nmb." year"));
}
function str_m($nmb){
    return date("Y年m月",strtotime("".$nmb." month"));
}
function str_d($nmb){
    return date("Y年m月d日",strtotime("".$nmb." day"));
}
//日付テキストの修正
function date_fix($text){
    $text=mb_convert_kana($text,"a");
    //ひらがなを漢字になど
    $ptn1=array("/おととし/", "/きょねん/", "/さくねん/", "/ことし/", "/さらいねん/", "/らいねん/", "/よくねん/", "/せんせんげつ/", "/せんげつ/", "/ぜんげつ/", "/こんげつ/", "/さらいげつ/", "/らいげつ/", "/じげつ/", "/おととい/", "/きのう/", "/ぜんじつ/", "/きょう/", "/あさって/", "/あした/", "/よくじつ/", "/さきおととい/", "/しあさって/", "/カ月/", "/か月/", "/ヵ月/", "/ケ月/");
    $rpc1=array("一昨年", "/去年", "/昨年", "今年", "再来年", "来年", "翌年", "先々月", "/先月", "/前月", "今月", "再来月", "来月", "次月", "一昨日", "昨日", "前日", "今日", "明後日", "明日", "翌日", "一昨々日", "明々後日", "ヶ月", "ヶ月", "ヶ月", "ヶ月");
    $text=preg_replace($ptn1,$rpc1,$text);
    //今から起算して系
    if(preg_match("/^(?P<nmb>[0-9]+)年(?P<f>前|後)(の)?/",$text,$m)==1){
        $rpc=str_Y(($m["f"]=="" ? "-" : "+").$m["nmb"]);
        $text=preg_replace("/([0-9]+)年(前|後)(の)?/",$rpc,$text);
    }
    if(preg_match("/^(?P<nmb>[0-9]+)ヶ月(?P<f>前|後)(の)?/",$text,$m)==1){
        $rpc=str_m(($m["f"]=="" ? "-" : "+").$m["nmb"]);
        $text=preg_replace("/([0-9]+)ヶ月(前|後)(の)?/",$rpc,$text);
    }
    if(preg_match("/^(?P<nmb>[0-9]+)日(?P<f>前|後)(の)?/",$text,$m)==1){
        $rpc=str_d(($m["f"]=="" ? "-" : "+").$m["nmb"]);
        $text=preg_replace("/([0-9]+)日(前|後)(の)?/",$rpc,$text);
    }
    //曜日系
    $weektext=array("","","","","","","");
    if(preg_match("/^(?P<next>(次の)+)(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2>=($w1=date("w")) ? $w2-$w1 : $w2-$w1+7)+(mb_substr_count($m["next"],"次の")-1)*7),$text);
    }
    if(preg_match("/^(?P<prev>(前の)+)(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2>=($w1=date("w")) ? $w2-$w1-7 : $w2-$w1)-(mb_substr_count($m["prev"],"前の")-1)*7),$text);
    }
    if(preg_match("/^(?P<nmb>[0-9]+)(回|週|つ|こ|個)(次|後|先)の(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2>=($w1=date("w")) ? $w2-$w1 : $w2-$w1+7)+($m["nmb"]-1)*7),$text);
    }
    if(preg_match("/^(?P<nmb>[0-9]+)(回|週|つ|こ|個)前の(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2>=($w1=date("w")) ? $w2-$w1-7 : $w2-$w1)-($m["nmb"]-1)*7),$text);
    }
    //週関連
    if(preg_match("/^(?P<next>(次の)+)週の(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2-date("w")+7)+(mb_substr_count($m["next"],"次の")-1)*7),$text);
    }
    if(preg_match("/^(?P<prev>(前の)+)週の(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
        $text=preg_replace("/^".$m[0]."/",str_d(($w2-date("w")-7)-(mb_substr_count($m["prev"],"前の")-1)*7),$text);
    }
    $ptn_week=array(-2=>"先々週",-1=>"先週",0=>"今週",1=>"来週",2=>"再来週");
    foreach($ptn_week as $nmb => $ptn){
        if(preg_match("/^".$ptn."の(?P<week>.*)曜/",$text,$m)==1 && ($w2=array_search($m["week"],$weektext))!==false){
            $text=preg_replace("/^".$m[0]."/",str_d($w2-date("w")+$nmb*7),$text);
        }
    }
    
    //実際の月に変換
    $ptn2=array("/^一昨年(の)?/", "/^去年(の)?/", "/^昨年(の)?/", "/~今年(の)?/", "/^再来年(の)?/", "/^来年(の)?/", "/^翌年(の)?/", "/^先々月(の)?/", "/^先月(の)?/", "/^前月(の)?/", "/今月(の)?/", "/^再来月(の)?/", "/^来月(の)?/", "/^次月(の)?/", "/^一昨日(の)?/", "/^昨日(の)?/", "/^前日(の)?/", "/今日(の)?/", "/^明後日(の)?/", "/^明日(の)?/", "/^翌日(の)?/", "/^一昨々日(の)?/", "/^一昨昨日(の)?/", "/^明々後日(の)?/", "/^明明後日(の)?/");
    $rpc2=array(str_Y("-2"), str_Y("-1"), str_Y("-1"), date("Y年"), str_Y("+2"), str_Y("+1"), str_Y("+1"), str_m("-2"), str_m("-1"), str_m("-1"), date("m月"), str_m("+2"), str_m("+1"), str_m("+1"), str_d("-2"), str_d("-1"), str_d("-1"), date("d日"), str_d("+2"), str_d("+1"), str_d("+1"), str_d("-3"), str_d("-3"), str_d("+3"), str_d("+3"));
    $text=preg_replace($ptn2,$rpc2,$text);
    return $text;
}

//日付抽出
function dateExtraction($text){
    $text=date_fix($text);
    $preg_str=array('/^(?P<year>[0-9]{4})\年(?P<month>[0-9]{1,2})\月(?P<day>[0-9]{1,2})日/',  //Y年m月d日
                    '/^(?P<year>[0-9]{4})\年(?P<day>[0-9]{1,2})日/',
                    '/^(?P<month>[0-9]{1,2})\月(?P<day>[0-9]{1,2})日/',
                    '/^(?P<day>[0-9]{1,2})日/',
                    '/^(?P<year>[0-9]{4})\-(?P<month>[0-9]{1,2})\-(?P<day>[0-9]{1,2})/',     //Y-m-d
                    '/^(?P<month>[0-9]{1,2})\-(?P<day>[0-9]{1,2})/',
                    '/^(?P<year>[0-9]{4})\/(?P<month>[0-9]{1,2})\/(?P<day>[0-9]{1,2})/',     //Y/m/d
                    '/^(?P<month>[0-9]{1,2})\/(?P<day>[0-9]{1,2})/');
    foreach($preg_str as $str){
        if(preg_match($str,$text,$m)==1){
            if(!isset($m["year"]))$m["year"]=date("Y");
            if(!isset($m["month"]))$m["month"]=date("m");
            if(checkdate($m["month"],$m["day"],$m["year"]))
                return date("Y-m-d",strtotime($m["year"].'-'.$m["month"].'-'.$m["day"]));
        }
    }
    return null;
}