ハッピーマンデーのように、ある月の何番目の曜日と指定して、日付を求めてみます。おまけに、最後の何曜日と後ろから数えられるようにもしましょう。
つぎのような関数xGetNthDay()を定義します。戻り値は指定した曜日のDateオブジェクトです。月はDateクラスと異なり1月を1から始めます。他方、序数(何番目)は第1を0とし、最後は-1から負の数で指定します。
xGetNthDay(年:uint, 月:uint, 序数:int = 0, 曜日:int = 0):Date
スクリプトの考え方は、つぎのとおりです。月内に該当する日付がないとき(たとえば第6月曜日)は、nullを返すことにします。
関数xGetNthDay()は、以下のスクリプト001のように定義しました。上記の1〜3は、剰余演算子%を使って1行で導いています。ちょっとしたパズルの感覚で、確かめていただくとよいでしょう[*1]。なお、Dateクラスのコンストラクタメソッドに日として0を渡すと、前月末の日付が得られます。
スクリプト001■年月と除数および曜日を渡して日付が返される関数function xGetNthDay(nYear:uint, nMonth:uint, nOrdinal:int = 0, nDay:int = 0):Date { var _date:Date; var nThisMonth:uint; if (nOrdinal > -1) { // 月初から数えるとき _date = new Date(nYear, nMonth - 1, 1); nThisMonth = _date.month; nDay = (nDay - _date.day + 7) % 7 + nOrdinal * 7; } else { // 月末から遡るとき _date = new Date(nYear, nMonth, 0); nThisMonth = _date.month; nDay = (nDay - _date.day - 7) % 7 + (nOrdinal + 1) * 7; } _date.date += nDay; if (_date.month != nThisMonth) { _date = null; } return _date; }
2011年1月の第1月曜日と2010年12月の最後の日曜日は、つぎのように求められます。
trace(xGetNthDay(2011, 1, 0, 1)); // 出力: Mon Jan 3 00:00:00 GMT+0900 2011 trace(xGetNthDay(2010, 12, -1)); // Sun Dec 26 00:00:00 GMT+0900 2010
ついでに、2011年のハッピーマンデーも掲げておきましょう。
// [1]成人の日: 1月の第2月曜日 2011年1月10日 trace(xGetNthDay(2011, 1, 1, 1)); // 出力: Mon Jan 10 00:00:00 GMT+0900 2011 // [2]海の日: 7月の第3月曜日 2011年7月18日 trace(xGetNthDay(2011, 7, 2, 1)); // 出力: Mon Jul 18 00:00:00 GMT+0900 2011 // [3]敬老の日: 9月の第3月曜日 2011年9月19日 trace(xGetNthDay(2011, 9, 2, 1)); // 出力: Mon Sep 19 00:00:00 GMT+0900 2011 // [4]体育の日: 10月の第2月曜日 2011年10月10日 trace(xGetNthDay(2011, 10, 1, 1)); // 出力: Mon Oct 10 00:00:00 GMT+0900 2011
[2010年12月15日追記] bkzenさんがwonderflに、この関数を用いた「何年何月何週目の何曜日が何日かを求める」というカレンダーつきのサンプルをつくられました。参考に掲載させていただきます。
何年何月何週目の何曜日が何日かを求める - wonderfl build flash online
[*1] 上記の「スクリプトの考え方」にしたがうと、式はつぎのように組立てられています。ただし、求めているのは厳密には「日付」でなく、月初から数えた「日数」になります(つまり、1日が0)。