« PEARのXML_Parserを使ったXMLパーサのクラス化(というか、移行方法) | トップページ | 見やすいPHPコードの書き方(但し我流) »

今日のお題:「祝日判定」

はじめに断っておきますが、万年カレンダーを作る、ってはなしではありません。

お仕事で祝日判定のルーチンを書くことになりまして。
国民の祝日について
…こんなふうに書きました。

function isholiday( $f_date ) {
    // 毎年 mmdd が変わらない日
    //                     元旦   建国   昭和   憲法   みど   こど 
    $fday_common = array( "0101","0211","0429","0503","0504","0505", 
    //                     文化   勤労   天皇   
                          "1103","1123","1223");
    // mmdd が変わる日+国民の休日
    $fday_alter  = array(
        // 2009               成人   春分   振替   海     敬老   国休 
            "2009" => array( "0112","0320","0506","0720","0921","0922",
        //                    秋分   体育
                             "0923","1012") ,   
        // 2010               成人   春分   振替   海     敬老   秋分 
            "2010" => array( "0111","0321","0322","0719","0920","0923",
        //                    体育
                            "1011") ,
        // 2011               成人   春分   海     敬老   秋分   体育
            "2011" => array( "0110","0322","0718","0919","0923","1010")
    ) ;
    $yy = substr( $f_date , 0 , 4 ) ;
    $mm = substr( $f_date , 5 , 2 ) ;
    $dd = substr( $f_date , 8 , 2 ) ;
    $mmdd = $mm . $dd ;
    if ( in_array( $mmdd , $fday_common       ) ) return TRUE ;
    if ( in_array( $mmdd , $fday_alter{ $yy } ) ) return TRUE ;
    // 以下省略

まぁ、はっきり言って

  • なんで(振替休日込みで)全部配列に突っ込んでるんだよー
  • 7月の第3週って設定くらいプログラムで書けよー
  • 春分日・秋分日くらい計算できるだろー

とかいろいろツッコミどころが多いと思います(苦笑)

まぁ、私としては、

  • 毎年1回更新するものだから、そのとき直すだけでいーじゃん
  • 休みはプログラムじゃなくて法律(人間の手)で決まるからどうせまた変わるしー

とかいうヌルい考えで組んだわけです(笑)

これだけじゃ、あんまりなんで、ちょっと遊んでみたいと思います。
twitterでこんなこと書いてみました。

そんなわけで、たとえば「1月の第2月曜日は何日になるかを求めるプログラムを書きなさい」とかいう課題は面白そうだとふと思った。

ぱっと思いついたのは、

1月の1日から数えて何回月曜日がくるかを数えて、2回目だったら祝日

という方法。
●年●月●日が何曜日かというのを求めるには、一番有名な方法としては、Zellerの公式、というのがありますが、今回は手抜きしてmktimeとdateでやっちゃいます。

$yy = 2009 ; // 年
$mm = 1 ;   // 月
$wnum = 2 ; // 第何週?
$wday=date("w",mktime(0,0,0,$mm,1,$yy));
$target_day = ( $wday > 1? $wnum : $wnum-1 ) * 7 + 2 -$wday ;

こっちのほうがわかりやすいかな。

$target_day = $wnum * 7 + 2 - ( $wday + ( $wday > 1 ? 0 : 7 ) ) ;

$wday>1 なのは、日曜が0、月曜が1、火曜が2、となっているためです。
日曜始まりの暦を見ると、月曜日は2番目に位置しています。だから +2 。
第何週なので、そのぶん*7します。
そこから、$wday (1日の曜日) をひきます。曜日が土曜日に向かうほど、月曜日が近くなりますから。

ざっとですが、コードと解説、かいてみました。

|

« PEARのXML_Parserを使ったXMLパーサのクラス化(というか、移行方法) | トップページ | 見やすいPHPコードの書き方(但し我流) »