Archive for the ‘Algorithm’ Category

その月の週数を求める

社内wikiにも書いたんですがもったいないのでこちらにものせちゃうことにしました。
Ajax絡みで第何週を選択するときに使うのによく使いそうなのでね。

問題

YYYY年MM月は第●週まである。●を求めよ
※ただし日曜はじまりとする

解答

3年分のカレンダーとにらめっこすれば見えてくると思います。
calコマンド多謝(笑)

  • 基本的に●=5
  • 2月の場合
    • 閏年であれば(29日)無条件に●=5
    • 閏年でなければ(28日)、1日が日曜日であれば●=4、それ以外は●=5
  • 2月以外の場合
    • 1日が土曜日であれば、無条件に●=6 (30日からが第6週になる)
    • 1日が金曜日であれば、31日の月(1,3,5,7,8,10,12)が ●=6、それ以外は●=5

なお、曜日判定は「Zellerの公式」で一発で片付ける。これは各自ぐぐってね。

せっかくなので、JavaScriptによる実装例を。(あくまで例)

function getWcount( iYear , iMonth ) {
   iYearN = iYear ; iMonthN = iMonth ;
   if ( iMonth == 1 ) { iMonthN = 13 ; iYearN = iYearN - 1 ; }
   if ( iMonth == 2 ) { iMonthN = 14 ; iYearN = iYearN - 1 ; }
   iWday = Math.floor( iYearN +
                       Math.floor(iYearN/4) - 
                       Math.floor(iYearN/100) +
                       Math.floor(iYearN/400) +
                       Math.floor( ( 13 * iMonthN + 8 ) / 5 ) + 1 ) % 7 ;
   iWcount = 5 ;
   if ( iMonth == 2  )  {
      if ( ( iYear % 4   ) == 0 &&
           ( ( iYear % 100 ) != 0 || ( iYear % 400 ) == 0 ) ) {
           // leap year !
           iWcount = 5 ;
       } else {
           if ( iWday == 0 ) { iWcount = 4 ; }
       }
   } else {
       if ( iWday == 6 ) { iWcount = 6 ; }
       if ( iWday == 5 ) {
           if ( iMonth == 1 || iMonth ==  3 || iMonth == 5 ||
                iMonth == 7 || iMonth == 8 || iMonth == 10 ||
                iMonth == 12 ) {
                iWcount = 6 ;
           }
       }
   }
   return iWcount ;
}

余談ですが、Zellerの公式で「3月始まり」になってることにお気づきでしょうか?
そういえば3月始まりというと、昔の暦のはじまりだよねーと。
ええ・・・9月~12月の呼び名が2つずれてるねとか。

参考: