※ 表示が正しくないと思う場合は、JavaScript を有効にしてください。
年 月 日の曜日
その日は何曜日だったのだろう?
指定の年月日の曜日を調べて、出力します。
日付を選択したら、「調べる」ボタンをタップ! その日が何曜日か、すぐにわかります。
イベント、誕生日、連休初日やクリスマス、年末年始、
あるいは歴史的事件の曜日を知って、予定を立てたり考えを深めよう!
選択できる年よりもっと前の日付を調べたい場合は「もっと前」ボタンをタップすれば、 選択できる年が、表示中のものより過去になります。 逆に、もっと先の日付を調べたい場合は「もっと先」ボタンをタップしてください。
※ 「年」指定で 0 〜 99 の値を指定した場合は、1900 年代と解釈されます。 これはシステムの都合なので、西暦 99 年より前は、正しく出力されません。
現時点でのテスト済みブラウザは、
です。
動作については、ある程度の検証は行っておりますが、 ご利用に関しては、自己責任でお願いします。 出力結果に誤りがあったとしても、当方では責任を負いかねます。
スマホやタブレットで開く場合は、
https://www.straightapps.com/web/js-day-of-week.html
)
投稿 February 2, 2021
ここから先は、上記、指定の日付の曜日を調べるプログラム開発を行った際に調べたりした JavaScript コードについての情報です。
作者背景については、「素因数分解トレーニング」のページの 「ここから先は開発情報です」をご覧ください。
まずは、HTML 部です。
<p id="today"></p> <span id="year"></span> 年 <!-- 年コンボボックス --> <span id="month"></span> 月 <!-- 月コンボボックス --> <span id="day"></span> 日の曜日 <!-- 日コンボボックス --> <button onclick="changeRange(0)" title="もっと前"> もっと前 </button> <button onclick="changeRange(1)" title="もっと先"> もっと先 </button> <p id="dow"></p> <button onclick="calc()" title="調べる"> 調べる </button> <script type="text/javascript" src="js/day-of-week.js"></script>
p id="today" の部分は、 「今日は 2021 年 2 月 2 日(火曜日)です。」のような表示になる場所です。 ページの読み込み時に、JavaScript で文字列を設定することで、表示されます。
続く span id="year" など3つの部分は、
コンボボックス(ドロップダウンリスト)が表示される部分です。
" " は、半角スペースを意味します。
確実に半角スペースを挿入するには、このように記述します。
そうでない場合、書く場所によっては、
button onclick="changeRange(0)" の部分は、ボタンを配置し、 押されたときの処理、JavaScript 関数の呼び出し指定を行うものです。
そして p id="dow" には、 調べた結果「2021 年 2 月 2 日は、火曜日です。」のような表示になるところです。
「調べる」ボタンは、押されたら JavaScript の calc 関数を呼び出すようになっています。
表示を更新する部分がすべて定義されたので、JavaScript を読み込んで、初期化等を実行しています。
以降のセクションで、それぞれ詳細を確認していきます。
なお、ご参考までに、JavaScript ソースコードそのものを、拡張子 js を拡張子 txt に変えて、次のリンクより開けるようにしてあります。
day-of-week-init.txt
day-of-week.txt
※ 作成時はタブを4文字としていますので、環境によってはタブが8文字のため、
コメント等がずれて見えるかも知れません。
※ 念のため書き添えますが、このソースコードをこのまま転載・公開することはご遠慮ください。
なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 February 2, 2021
JavaScript のコードは、初期化を行う day-of-week-init.js と、 実際の処理を行う day-of-week.js の2つから構成されています。
初期化を行う day-of-week-init.js は、 <head> 〜 </head> タグ内でロードしていますが、 この場所で読み込む場合は、ページ本体のデータ(body 部)が読み込まれる前に、ロードされるようです。
なので、この中で、例えばあとで定義されている p id="dow" にアクセスしようとしても、アクセスできません。
var date = new Date(); // 日付 var selYear = 0, selMonth = 0, selDay = 0; // 選択中の年・月・日 var baseYear = date.getFullYear(); // 表示する西暦年の初期値
day-of-week-init.js にあるのは上記のものだけです。
変数 date に、新しく作成した
2行目は、コンボボックスで選択した年月日を保持する selYear、selMonth、selDay を初期化しています。
最後は、年コンボボックスに表示する最初の年を保持する baseYear を、「今日」の年に設定します。 Date クラスの getFullYear 関数が、西暦年を返す関数です。 date には本日の日付を入れていますので、「今日」の年となります。 「もっと前」ボタンや「もっと先」ボタンで、この値が変更されます。
ほぼすべての機能が実装されている day-of-week.js は、 body タグ内でロードされています。 これは、HTML の body を先頭から読み込んでいき、 そのコードに到達したときに読み込まれる、というものです。
<script type="text/javascript" src="js/day-of-week.js"></script>
ここでは、これより前で定義された p id="today" や span id="year" にアクセスできます。
なお、JavaScript のコードは、head や body タグ内に直接記述することも可能です。 機能テストには有効かもしれませんが、ごちゃごちゃになるので、おすすめできる方法ではありません。 また、HTML タグの onClick などに直接コードを書くこともできるようですが、小規模でない限りは、混乱のもとになるかと思います。
<script type="text/javascript"> <!-- <!-- JavaScript コードを記述 --> // --> </script> <noscript> <!-- JavaScript が無効の場合の注意書きなどを記述 --> </noscript>
投稿 February 2, 2021
body が読み進まれていき、script の行まで到達すると、src で指定されたファイルが読み込まれます。
<script type="text/javascript" src="js/day-of-week.js"></script>
day-of-week.js は、 p id="today" や span id="year" にアクセスしますので、 この script の行は、それらよりあとに記述されていなくてはなりません。 一般的には </body> の直前でいいようですが、 このページでは、読みにくくならないように、 必要なすべての HTML 要素の定義が終わった直後、 つまり button の定義の直後に置いています。
なお、ただ単純に、ブラウザがその行を解析するときに読む、というだけのようですから、 script 行が複数あれば、それぞれそのタイミングで読み込まれるようです。
day-of-week.js の先頭部分は、次のような流れになっています。
まずは、本日の日付を表示しています。
var elem; var str, strTmp; // 本日の日付を表示します。 elem = document.getElementById("today"); str = "今日は " + date.getFullYear() + " 年 " + (date.getMonth()+1) + " 月 " + date.getDate() + " 日(" + getDayOfWeek(date.getDay()) + ")です。"; elem.innerHTML = str;
p id="today" の部分を、innerHTML を設定することにより、 書き換えています。 innerHTML の利用について、詳しくは、「【基礎】HTML 要素のテキストの書き換え」 に書いています。
今日の日付を得るために、 day-of-week-init.js で作成している、Date クラスのオブジェクト date の関数を呼び出しています。 getFullYear() 関数は、西暦年を返します。 getMonth() 関数は、月を、0 〜 11 で返します。 なので、1 〜 12 月にするためには、+1 しなくてはいけません。 getDate() 関数は、日を返します。
getDay 関数は、曜日を 0 〜 6 で返します。 数値ではわかりにくいので、このあと定義している getDayOfWeek 関数に渡して、日本語表記にしています。
JavaScript は型の概念が薄いので、 数値や文字列の区別なく文字列として連結し、いったん str に入れています。 それを innerHTML にセットする手順にしていますが、 1行で文字列を作成するなら、 いったん str に入れなくても直接 innerHTML に入れられるのではないかと思います。 コードは読みにくくなりますから、直接じゃないほうがいいでしょう。
また、月を連結している部分、 「(date.getMonth()+1) + " 月 "」のようにカッコでくくっています。 もし「date.getMonth() + 1 + " 月 "」にすると、 例えば 2 月なら、getMonth() が 1 を返しますが、 出力は「11 月 」になってしまいます。 つまり、"1" + "1" + " 月 " と解釈されています。 カッコで優先順位を与えれば、解決されます。
続けて、年・月・日コンボボックス(ドロップダウンリスト)を作成しています。
// 年コンボボックスを作成します。 setYearCombo(); // 月コンボボックスを作成します。 setMonthCombo(); // 日コンボボックスを作成します。 setDayCombo(true);
これらの関数については、あとで解説します。
最後に、p id="dow" の部分の初期表示を設定しています。 dow は、day of week、つまり曜日の省略形です。
elem = document.getElementById("dow"); elem.innerHTML = '日付を指定し、「調べる」ボタンを押してください 〜以降 文字列省略〜。';
このあとは関数の定義しかありませんので、 この day-of-week.js の HTML 読み込み時の実行は終わり、続きの HTML が読み込まれていくことになります。
「素因数分解トレーニング」では、 描画のために、意味なく main ループを定義し、 addEventListener 関数で、ページ読み込み完了後のスタートさせていましたが、 このプログラムでは、ループさせるコードはありません。
投稿 February 2, 2021
<span id="year"></span> の部分に、 「年」を表すコンボボックス(ドロップダウンリスト)を作成し、表示しています。 なお、「コンボボックス」は Windows PC での呼び方で、 クリックすると表示される項目リストから1つ選ぶ、というものです。
day-of-week.js が読み込まれたときに呼び出される、 setYearCombo 関数 で実行されています。
function setYearCombo() { elem = document.getElementById("year");
ここにセットしたい HTML 文字列は、次のようなものです。
<select name="year" id="to-year" onChange="changeYear(this.value)"> <option value="2021"> 2021 </option> <option value="2022"> 2022 </option> <!-- 同様の部分は省略 --> </select>
すなわち、HTML の select タグで、ドロップダウンリストを作成します。 リストになる項目は、option タグで定義できます。 好きな個数だけ option タグを定義したあと、select タグを閉じれば OK です。
select タグにある onChange は、 選択が変更されたときに実行される関数を定義するものです。 day-of-week.js 内で定義している、 changeYear 関数 に、 選択された option の value で指定している値を、引数として渡すということになります。
決まった値だけから選択するだけなら(例えば月は、いつでも 1 〜 12 月しかないので)、 HTML に直接 select/option を書けばよいのですが、 年には、(初期状態では)「今日」の年から、この先 10 年分を表示したかったので、JavaScript で出力しています。 つまり、2021 年なら 2031 年まで選択可能となり、2022 年なら 2022 年から 2032 年までが選択可能となります。
また、「もっと前」や「もっと先」ボタンが押されたときには、 選択可能な年を変更できるようにしますので、 HTML に直接書き込んでしまうと、実現できなくなります。
それをコードにし、innerHTML に設定するまでが、下記の部分です。
str = '<select name="year" id="to-year" onChange="changeYear(this.value)">'; // select 内で size="3" 指定すると、3要素を同時表示するようになる for (var i = 0; i <= 10; i ++){ strTmp = ('<option value="' + (baseYear+i) + '"> ' + (baseYear+i) + ' </option>'); str += strTmp; } str += '</select>'; elem.innerHTML = str;
for ループ内の strTmp 作成に使用している baseYear が、 現在先頭に表示すべき年で、初期状態は、js-day-of-week-init.js で設定している「今日」の年です。
最後に、曜日調査時に参照するため、選ばれた値を selYear に設定しています。 変数 selYear は、day-of-week-init.js で定義されています。
// 選択中の年を記録 selYear = baseYear; }
option タグで、どれにも selected 指定をしていませんので、 先頭の項目が選ばれるため、baseYear となります。
投稿 February 2, 2021
「月」のドロップダウンリストも、「年」と同じように、 select タグと option タグを用意し、 span id="month" の innerHTML を書き換えています。
選択が変更されたときに呼び出される関数は、changeMonth( this.value ) です。
「年」よりは「月」のほうが本来簡単なのですが、 1桁と2桁の数字を単純に出力すると左寄せになってしまいますので、 見た目向上のため、1桁のときは数字の前にスペースを入れて、調整しています。 また、初期状態で「今月」が選ばれるようにしています。
まずは関数の定義と、span id="month" を取得しています。
function setMonthCombo() { elem = document.getElementById("month");
変数 str に、select タグを用意します。 選択が変更されたときに呼び出される onChange には、 changeMonth 関数を指定しています。 引数に this.value を指定していますので、 option タグの value で指定された値が渡されることになります。
str = '<select id="to-month" onChange="changeMonth(this.value)">';
今見直すと、elem も str も、定義しないで使っています。 もちろん本来は var を付けるべきですが、これでも大丈夫なところが・・・怖いと言えます。
var month = date.getMonth() + 1; for (var i = 1; i <= 12; i ++){ if (i == month){ if ( i < 10 ){ strTmp = ( '<option value="' + i + '" selected> ' + i + ' </option>' ); } else{ strTmp = ( '<option value="' + i + '" selected> ' + i + ' </option>' ); } } else if ( i < 10 ){ strTmp = ( '<option value="' + i + '"> ' + i + ' </option>' ); } else{ strTmp = ( '<option value="' + i + '"> ' + i + ' </option>' ); } str += strTmp; }
変数 month には、day-of-week-init.js で定義し、 本日の日付データが入っているオブジェクト date を用いて、今月を取得しています。 getMonth 関数が 0 〜 11 を返すため、1 を足して、1 〜 12 に直しています。
それぞれの月に option タグを作ります。 value は月そのものの値とし、1桁の場合は数字の前にスペースを入れています。 また、設定する数値が「今月」と一致するなら、option タグに selected を付けて、 初期状態でそのオプションが選ばれた状態になるようにしています。 いずれもいったん strTmp に option タグ全体をセットしてから、 str に追加しています。
str += '</select>'; elem.innerHTML = str; // 選択中の月を記録 selMonth = month; }
最後に select タグを閉じ、innerHTML で書き換えています。 selMonth には、選択されている値をセットします。 初期状態では、date から取得した month が、選択状態になっています。
投稿 February 2, 2021
「日」ドロップダウンリストも、 select タグを用意し、選択肢を option タグで定義するところは同じです。 初期状態で選択される値には、selected を追加しておきます。
「日」で面倒なのは、「月」が変更されたとき、選べない日を表示しないよう、更新する処理です。 例えば 10 月が選ばれているなら 31 日まで表示しますが、 9 月が選ばれたときには 30 日までに書き換えます。 このとき、例えば 15 日が選択されていたなら、「月」が変更されても 15 日が選択された状態としたいです。 また、10 月 31 日が選ばれているとき、9 月が選択されたら、9 月には 31 日がないので、 自動的に 30 日を選択しなおすほうが親切です。 さらに、2 月の場合、うるう年があるので、「年」が変更されたときも気にする必要があります。
setDayCombo 関数は、引数 bToday を得ています。 true が渡された場合は起動時の初期化を行います。 この場合は、選択される日付が「今日」になります。 false が渡された場合は、選ばれている日付をキープします。
function setDayCombo(bToday) { elem = document.getElementById("day"); str = '<select id="to-day" onChange="changeDay(this.value)">';
変数 str には、select タグを設定しています。 選択が変更されたときは、onChange で指定している changeDay 関数 が呼び出されます。
var day = date.getDate(); if (bToday == false){ day = selDay; }
変数 day に、day-of-week-init.js で定義した本日のデータ、 date を使用して、日付を取得しています。 引数 bToday で false が渡された場合、すなわち初期化ではない場合、 day を今選択されている日 selDay で上書きし、 日がキープされるようにします。
var eom = new Date( selYear, selMonth, 0 ).getDate(); // 選択中年月の End of Month if (day > eom){ day = eom; }
変数
以下、「月」と同じように、1桁の場合は先頭にスペースを入れながら、 day と一致する選択肢に selected を入れる、 というコードになっています。 「コード詳細を確認」を展開して、確認していただけます。
投稿 February 2, 2021
select タグの onChange に JavaScript の関数を記述すると、 選択が変更されたときに、その関数が呼び出されます。
「年」ドロップダウンリストの場合、 select onChange="changeYear(this.value) のように書いていますので、 選択が変更されたとき、changeYear 関数が呼び出されます。 引数は、option の value に書かれた値で、ここでは 2021 や 2022 のようになります。 仮引数名 selectedYear で受け取ります。
function changeYear(selectedYear) { // うるう年に当たる場合は、2月の日数が変わります。 selYear = selectedYear; // 2月選択中以外は、何もする必要はありません。 if (selMonth != 2){ return; } // うるう年かもしれないので、日コンボを再設定します。 // 2月に29日がある、or 2月29日選択中だが無効 setDayCombo(false); }
引数で受けた、新しく選択された年 selectedYear を、現在の選択として selYear にコピーしています。
もし今 2 月が選ばれている場合、うるう年のため、日数が変わるかも知れません。 つまり、今 2 月 29 日を選択中なら、2 月 29 日がない年が選択された場合は、28 日にすべきです。 2 月以外の場合は、年だけの変更なら月日には影響はないので、そこで関数を終了します。
2月の場合、「日」ドロップダウンリストを再初期化するため、setDayCombo 関数を呼び出します。 引数を false にしていますので、できるだけ今選択されている日がキープされます。
同様に、「月」ドロップダウンリストの選択が変更された場合は、 次の changeMonth 関数が呼び出されます。
function changeMonth(selectedMonth) { selMonth = selectedMonth; // 日コンボを再設定します。 setDayCombo(false); }
引数で受けた、新しく選択された月 selectedMonth を、現在の選択として selMonth にコピーしています。
月が変わると日数も変わる可能性がありますので、setDayCombo 関数を呼び出しています。 引数を false にしていますので、できるだけ今選択されている日がキープされます。
「日」ドロップダウンリストは、簡単です。
function changeDay(selectedDay) { selDay = selectedDay; }
引数で受けた、新しく選択された selectedDay を、現在の選択として selDay にコピーしています。
これにより何か書き換える必要はありませんので、これだけです。
投稿 February 2, 2021
初期状態では、選択できる年は、「今日」の年から、その先 10 年となっています。
もっと前の日付の曜日を調べたい場合は「もっと前」ボタン、 もっと先の日付の曜日を調べたい場合は「もっと先」ボタンにより、 選択できる年のリストを更新することにしています。 初期状態で前後 30 年などと広くとっても、リストが伸びて選択しにくくなるだけでなく、 結局それを超える場合は「もっと」ボタンが必要になるので、 適度な年数が良いと思います。
「もっと前」ボタンが押されたときには changeRange 関数に引数 0 が渡され、 「もっと先」ボタンが押されたときには changeRange 関数に引数 1 が渡されることになっています。
function changeRange(param) { // 「もっと前」の場合 if (param == 0){ baseYear -= 10; } // 「もっと先」の場合 else if (param == 1 ){ baseYear += 10; } // それ以外 else{ return; }
引数 param が 0 なら、 年コンボ(リスト)に表示する先頭の年 baseYear をマイナス 10、 すなわち今表示している年の先頭の 10 年前からとします。
同様に、引数 param が 1 なら、年コンボの先頭の年 baseYear をプラス 10 して、10 年後からとします。
param がその他の値であれば、何もしません。 すべて自作のコードですので、例外的な処理は不要とも言えなくもないですが、 一般的には、入れておくほうが安全です。 ただ、この場合は、baseYear に変更なく処理が続行されるだけなので、 無駄な処理を行い、選択中の年がリストの先頭に変更されてしまう、という程度で済みますが・・・。
setYearCombo();
selYear = baseYear;
年リストを、setYearCombo 関数を呼び出して、再作成します。 setYearCombo 関数は、baseYear から始まる、その先 10 年分の年をセットします。
年リストを更新すると、選択されている年が変わりますので、selYear も更新します。
if (selMonth != 2){ return; } setDayCombo(false); }
あとは、年が変更されたときに呼び出される関数 changeYear と同じように、 2 月 29 日を選択中に年が変更された場合の対応を行って、終了です。
投稿 February 2, 2021
「調べる」ボタンは、HTML で button onclick="calc()" と定義されていますので、 押されたときに JavaScript の calc 関数が呼び出されます。
function calc() { var targetDate = new Date(selYear, selMonth - 1, selDay);
Date 関数を調べる前は、 2021 年 1 月 1 日が金曜日であるところから、 指定の年の 1 月 1 日の曜日を計算で決めて、 そこから何日経過しているかを計算し、 7 で割ったあまりを・・・ とするイメージでしたが、今どき、そんなことは不要でした。
上記のように、Date オブジェクトを指定の日付で作成するだけで、 曜日も自動的にセットされる、という具合でした。 それが信用できるのか、という点については、信用する、ということで。
コンストラクタに渡す第1引数は西暦年、第2引数は 0 ベースの月、第3引数は 1 ベースの日付です。
第1引数で指定する西暦年は、例外があるようです。 0 〜 99 を指定した場合に限り、1900 年から 1999 年として扱われる、とされています。 あれからもう 20 年以上が経過していますが、 1999 年より前、年を 2 桁で書くコードがありました。 コンピューター初期の頃、8 ビット CPU の時代には、1 バイト 0 〜 255 が処理単位でしたので、 4 桁の西暦年を表すには、2 バイト必要です。 非常に少ないメモリ容量の時代に、年を 1 つ表すのに 1 バイトずつ多く使用するのがもったいなく、 10 進数 2 桁で管理したため、Y2K、2000 年問題が発生しました。 つまり、年が 99 の次、00 になったとき、2000 年ではなく 1900 年と誤認する、というものです。 当時、入念な事前の準備もあり、それほど大きな問題は起きなかったと思われますが、 おかげで今、このコードでは、西暦 1 年から 99 年の曜日を調べることはできません。 また、西暦 0 年やマイナス年の場合、エラーはでませんが、正しいかどうかはわかりません。 試したい方は、js-day-of-week-init.js の baseYear の初期値を書き換えると簡単です。
第2引数で指定する月は、1 月なら 0、2 月なら 1 というように、0 を基準とする値です。 getMonth 関数で得られる値と一致ですが、わかりにくいです。 注意が必要です。
第3引数で指定する日は、1 日なら 1、2 日なら 2 の、1 基準ですので、わかりやすいです。 月末の日を知るために使ったように、ここに 0 を指定すると、月末の日付となるようです。
elem = document.getElementById("dow"); str = targetDate.getFullYear() + " 年 " + (targetDate.getMonth()+1) + " 月 " + targetDate.getDate() + " 日は、" + getDayOfWeek(targetDate.getDay()) + "です。"; elem.innerHTML = str; }
調べた結果を出力します。 いったん str に、表示したい文字列を作成して、innerHTML で置き換えています。
曜日は Date クラスの getDay 関数が返しますが、0 は日曜日、1 は月曜日のように、数値で返ってしまいます。 日本語に変換するために、getDayOfWeek 関数を用意しました。
function getDayOfWeek(dow) { switch (dow){ case 0: return "日曜日"; case 1: return "月曜日"; case 2: return "火曜日"; case 3: return "水曜日"; case 4: return "木曜日"; case 5: return "金曜日"; case 6: return "土曜日"; } return "不明"; }
引数 dow は 0 〜 6 の数値であるとし、 switch 文で分岐させて、該当する文字列を返しています。
引数 dow が 0 〜 6 ではない場合は、switch 文を抜けて、「不明」を返します。
switch 文の default を使えば、同じ処理を実現できます。 プログラミング言語(コンパイラ)によっては、 「値を返さないコントロールパスがある」というようなエラー(警告)になるので、 このようにしています。 JavaScript では、値を返す関数と返さない関数に区別はなく、 またコンパイルもありませんので、default で処理しても同じです。
ウェブ開発に関するトピックは、「ウェブ開発トップ」にまとめられています。
SSD + HDD デュアル搭載のデスクトップ機で、 システム入り SSD を大容量のものに交換したときの様子を書いています。