Calendar
万年カレンダーのサンプル
サンプルのディレクトリ構成
- index.html
- style.css
- script.js ネイティブ JavaScript です。ライブラリ等は不要です。
付記
- HTMLでは、年・月を選択する SELECT も、カレンダーそのものである TABLEも、枠組みのみ与えています(内容はすべて JavaScript で生成して埋め込む形になっています)。
プログラムの解説
西暦XXXX年XX月のカレンダーは、以下の2つがわかれば作成できます。
- 当該月の1日が何曜日であるか
- 当該月の日数が何日であるか
このサンプルでは、西暦年と月を<select> から取得し、当該年月のカレンダーを表示しています。以下、JavaScript のソースを上の方から順に概説します。
- はじめに monthsOfTheYear[]、daysOfTheWeek[] の2つの配列それぞれに、月名と曜日名を定義しています。
- その後、年と月の select 部分に option を登録、また表のヘッダーに SUNからSAT までの曜日名を登録しています。
- 年・月と、prev ( < ) / next ( > ) ボタンにイベントリスナーを登録
いずれも選択された年 year と 月 month をもって、カレンダーを生成する関数setCalendar() に作業を渡します。
- 本日の日付情報を取得
let today = new Date();
- 本日が何月かを取得
let thisMonth = today.getMonth();
0から11の整数で返されるので、数字として表示する場合は +1 が必要。
月名が配列にある場合は、monthsOfTheYear[0] が1月で都合がいい。
- 本日の西暦年の値を取得する
let thisYear = today.getFullYear();
- 本日を含む年月のカレンダーを表示
setCalendar(thisYear, thisMonth);
ページ読み込み後の主たる処理は以上です。
以下、関数です。
- displayDate() は、日付の数字がクリックされたときのイベントハンドラで、日付クリックの際に、何らかの処理を行う機能を追加したい場合のサンプルとして書いているものです。ここでは、単にクリックされた日付を確認するためのアラートダイアログを表示しています。
- setCalendar() は、年 thisYear と 月 thisMonth をもって、当該年月のカレンダーを作成するプログラム本体です。
- 当該年月の日数を取得
let days = new Date(year, month+1, 0).getDate();
ちょっと面倒で「当月末日 = 翌月の0日 が何日か」という方法で取得
getDate() は日の値を 1 から 31 の数値で返します。 1 :1 日、 31: 31 日
- 当該年月の 1日の曜日を取得
let firstDay = new Date( year, month ).getDay();
getDay() は曜日を0 から 6 の数値で返します。0 :日曜、 1:月曜・・
- 続く for の2重ループでカレンダーを生成
- 行のループ(最大6行)で <tr> を追加(appendChild)
- 列のループ(7回)で <td> すなわち cell を追加(appendChild)
- 1日の曜日までは空送り
- もし、当該cell が「本日」であった場合は id を "today" とする
- 行内で最終日を超えたら、その行が埋まるまでから送り
- DOMが完成したところで(HTML要素が登録されたところで)次の2重ループで、各日付にイベントリスナーを登録(日付クリックで何か機能を追加するための参考的な処理)
- 当該年月の日数を取得
- moveNext() は Nextボタン(>)のクリックに対するイベントハンドラ
- movePrevious()は Prevボタン(>)のクリックに対するイベントハンドラ
- changeView() は年月が選択された場合のイベントハンドラ
参考 Date()オブジェクト
本日の日時情報は、以下のようにして console に表示することができます。
var today = new Date(); var year = today.getFullYear(); var month = today.getMonth() + 1; var day = today.getDate(); console.log( year + '年' + month + '月' + day + '日');
APPENDIX
万年カレンダーの一般的なアルゴリズム
プログラミング学習では万年カレンダーは定番の課題。既存の関数を使わずに、計算によってそれを表示させるには、以下のようなロジックを利用します。
西暦XXXX年XX月のカレンダーは、以下の2つがわかれば作成できます。
- 当該月の日数が何日であるか
- 当該月の1日が何曜日であるか
当該月の日数が何日であるかは基本的には決まっているので、1月から12月までの日数を配列に準備し、閏年にあたる場合のみ、2月を29日とすればよい・・ということになります。当該年が閏年かどうかは、以下の判定で得られます。
西暦が 4 で割り切れる年を閏年とする ただし 100 で割り切れる年は平年とする ただし 400 で割り切れる年は特別に閏年とする
当該月の1日が何曜日であるかは、「過去の基準日の曜日」と「基準日から当該年月の1日までの総日数」が求まれば、その日数を7で割って曜日を求めることができます。
カレンダーの1行目は、1日の曜日まで「空送り」して、そこから数字をひとつづつ増やしながら、最終日まで表を埋めて完成です。