「カレンダーを作る(1)」ではページを読み込むと今月のカレンダーが表示され、今日の日付が違う色で強調されるものを作ってみました。 今回は、1900年1月から2099年12月までの200年間の指定した月のカレンダーを表示するプログラムを作ってみます。 以前は1920年1月から1999年12月までの80年間分だけでしたが、ご要望に応えて2000年8月1日、新しくしました。(Internet Explorer 3.0 以上、Netscape 2.0 以上に対応しています。)
そのために、今回は TABLE タグのほかにドロップダウン・リストが4個、ボタンが1個、テキストボックスが39個必要になります。 <BODY> 内の適当な場所に以下のフォームを設定します。
- <FORM NAME="calendar">西暦
- <SELECT NAME="century">
- <OPTION selected>19
- <OPTION>20
- </SELECT>
- <SELECT NAME="decade">
- <OPTION selected>0
- <OPTION>1
- <OPTION>2
- <OPTION>3
- <OPTION>4
- ・
- ・
- ・
- <OPTION>8
- <OPTION>9
- </SELECT>
- <SELECT NAME="year">
- <OPTION selected>0
- <OPTION>1
- <OPTION>2
- <OPTION>3
- ・
- ・
- ・
- <OPTION>8
- <OPTION>9
- </SELECT>年<P>
- <SELECT NAME="month">
- <OPTION selected>1
- <OPTION>2
- <OPTION>3
- <OPTION>4
- ・
- ・
- ・
- <OPTION>10
- <OPTION>11
- <OPTION>12
- </SELECT>月
- <INPUT TYPE="button" VALUE="選択" onClick="Koyomi()"><P>
- <TABLE border=1 cellspacing=0 bgcolor="yellow"><TD>
- <TABLE>
- <TR>
- <TD colspan=7 align=center>
- <INPUT TYPE="text" SIZE=5 MAXLENGTH=4>年<INPUT TYPE="text" SIZE=2 MAXLENGTH=2>月
- </TD>
- </TR>
- <TR>
- <TD align=center><FONT color="red">日</FONT></TD>
- <TD align=center>月</TD>
- <TD align=center>火</TD>
- <TD align=center>水</TD>
- <TD align=center>木</TD>
- <TD align=center>金</TD>
- <TD align=center>土</TD>
- </TR>
- <TR>
- 以下、</TR>(1) まで
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>
- を7回繰り返す
- ・
- ・
- ・
- </TR>(1)
- <TR>
- 以下、</TR>(2) まで
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>(2)
- を7回繰り返す
- ・
- ・
- ・
- </TR>(2)
- <TR>
- 以下、</TR>(3) まで
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>(3)
- を7回繰り返す
- ・
- ・
- ・
- </TR>(3)
- <TR>
- 以下、</TR>(4) まで
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>(4)
- を7回繰り返す
- ・
- ・
- ・
- </TR>(4)
- <TR>
- 以下、</TR>(5) まで
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>
- を7回繰り返す
- ・
- ・
- ・
- </TR>(5)
- <TR>
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>
- <TD><INPUT TYPE="text" SIZE=2 MAXLENGTH=2></TD>
- </TR>
- </TD>
- </TABLE></TABLE></FORM>
TABLE を二重にしているのは、外側の TABLE で枠と色を指定するためです。プログラムの実行には関係ありません。
仕上がりは、次のような外観になります。上の3つのドロップダウン・リストから西暦を、その下のドロップダウン・リストから月を選び、選択ボタンを押すと指定した年・月のカレンダーが表示されます。
もちろん前述のフォームを設定しただけでは、この機能は実行されません。ボタンの onClick で呼び出される Koyomi() 関数を定義しなければボタンを押してもエラーになります。
HTML の </TITLE> と</HEAD> の間に次のように始めます。
- function Koyomi() {
- with(document.calendar)
- {
- var S=6;
- for(i=0; i < 37; i++)
- {
- S++;
- elements[eval(S)].value="";
- }
これはつまりデータの初期化をやっています。1度或る月を読み込んで、次に別の月を読み込んだとき、前のデータが残らないように日付の欄を1度すべて空白にしているわけです。
次に、ドロップダウン・リストから選択された数字を変数に入れます。これらをカレンダー上部のテキストボックスに入れます。
- ce=decade.selectedIndex;
- CE=decade.options[ce].text;
- de=decade.selectedIndex;
- DE=decade.options[de].text;
- ye=year.selectedIndex;
- YE=DE+year.options[ye].text;
- mo=month.selectedIndex;
- MO=month.options[mo].text;
- elements[5].value=CE+YE;
- elements[6].value=MO;
これで選択された西暦と月がテキストボックスに表示されるようになりました。次いで、先ほどの変数を数値に変換します。 ドロップダウン・リストから得られたデータは数字とはいっても文字列で、文字列型変数では計算はできないからです。
- A=parseInt(CE);
- Y=parseInt(YE);
- M=parseInt(MO);
- N=parseInt(CE+YE);
次に、指定された月の日数を割り出さなければなりません。2月30日とか4月31日とかのあり得ない日付が表示されては困るからです。 これには「カレンダーを作る(1)」で述べた Nissu() 関数をここでも使うことにします。Koyomi() 関数とは独立にこの関数を定義しておきます。
- function Nissu(a, b) {
- if(b==2)
- {
- if(a % 4==0)
- {
- if(x % 100==0 && x % 400!=0) return 28;
- else return 29;
- }
- else return 28;
- }
- else if(b==4 || b==6 || b==9 || b==11) return 30;
- else return 31;
- }
Koyomi() 関数に戻って、Nissu() で割り出された日数を Days という変数に代入します。
- Days=Nissu(N, M);
さてカレンダーを作るためには、その月の1日が何曜日であるか知らなければなりません。 西暦・月・日からその日の曜日を割り出す Zellar の公式というのがあります。これは(西暦の上2桁をA、西暦の下2桁をYで表示すると)、
- (A÷4−2×A+Y+(Yを4で割った整数)+26×(月+1)を10で割った整数+日−1)を7で割った剰り
で、今問題となっているのは毎月の1日ですから、最後の日−1は省略できます。 またこの Zellar の公式では1月、2月はそれぞれ前年の13月、14月として計算しなければならない約束となっていますので、まず
- if(M<=2)
- {
- M+=12;
- Y-=1;
- }
としてから変数 First に Zellar の公式で得られた数値を入れます。
- First=(Math.floor(A/4)-2*A+Y+Math.floor(Y/4)+Math.floor((26*(M+1)/10)))%7;
ここで問題となるのは整数が整数で割り切れないようなとき、/ の代わりにBASIC なら \、Pascal なら div を使いますが、JavaScript には適当な演算子がないので Math.floor() というメソッドで処理してやるということです。
さていよいよカレンダーの本体部分です。
- First+=6;
- if(First < 6) First+=7;
- var Hi=0;
- for(i=0; i < Days; i++)
- {
- First++;
- Hi++;
- elements[eval(First)].value=Hi;
- }
- }
- }
月の1日が水曜日とすると First に入る数字は3ですから日付を入れるボックスの左から4番目(0から数えて3番目)に入るはずですが、 日付を入れるテキストボックスはこのフォームの(最初を0とした場合の)7番目にあるのであらかじめ First に6を加えてやります。 for ループが始まると3+6に1加算されるのでフォームの10番目のエレメント、つまり「水」の真下のボックスに"1"が表示されるという寸法です。 (Hi は日付を入れる変数です。)
* 但し西暦の下2桁が16以下の年(1915年、2001年など)には First の値が6以下を返して正常に表示されないため、その場合には7を加えていることに注意して下さい。 これは今回の変更で新たに付け加えた点です。