PHPで祝日を求める

(3/4)

サンプル・プログラムの解説:移動祝日1

0142: /**
0143:  * ある年の春分の日を求める
0144:  * @param int $year 西暦年
0145:  * @return int 日(3月の)
0146: */
0147: function getVernalEquinox($year) {
0148:     return floor(20.8431 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
0149: }
0150: 
0151: /**
0152:  * ある年の秋分の日を求める
0153:  * @param int $year 西暦年
0154:  * @return int 日(9月の)
0155: */
0156: function getAutumnalEquinox($year) {
0157:     return floor(23.2488 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
0158: }
0159: 
0160: /**
0161:  * 移動祝日(春分/秋分の日)であれば、その名称を取得する
0162:  * @param int $year  西暦年
0163:  * @param int $month 月
0164:  * @param int $day   日
0165:  * @param string lang jp=日本語名称/en=英語名称
0166:  * @return string 移動祝日の名称/FALSE=祝日ではない
0167: */
0168: function getMovableHoliday1($year$month$day$lang) {
0169:     $name = FALSE;
0170: 
0171:     //春分の日
0172:     $dd = getVernalEquinox($year);
0173:     if ($year >=1949 && $day == $dd && $month == 3) {
0174:         $name = preg_match("/JP/i", $lang) == 1 ? '春分の日' : 'Vernal Equinox Day';
0175:     }
0176:     //秋分の日
0177:     $dd = getAutumnalEquinox($year);
0178:     if ($year >=1948 && $day == $dd && $month == 9) {
0179:         $name = preg_match("/JP/i", $lang) == 1 ? '秋分の日' : 'Autumnal Equinox Day';
0180:     }
0181:     return $name;
0182: }

秋分の日と敬老の日の微妙な関係」で述べたように、「春分の日」「秋分の日」は前年度の閣議で決まる。これが一番厄介である。
秋分の日、秋分の日を天文学的な計算する手段はあるのだが、人為的に日付を変える可能性があるので、こればかりは計算で確実に求めることができない。
space
ユーザー関数 getVernalEquinox は天文学的に春分の日を、getAutumnalEquinox は秋分の日を計算するものである。
あくまで計算で求めているので、実際のカレンダーとは±1 日程度ズレる可能性があることに留意されたい。すでにカレンダーとして決まっている 2009 年以前の春分の日、秋分の日も計算によって求めているので、過去のカレンダーと合致しないかもしれない。
space

サンプル・プログラムの解説:移動祝日2

0184: /**
0185:  * ある月の第N曜日を求める
0186:  * @param int $year 西暦年
0187:  * @param int $month 月
0188:  * @param int $week  曜日番号;0 (日曜)〜 6 (土曜)
0189:  * @param int $n     第N曜日
0190:  * @return int $day 日
0191: */
0192: function getWeeksOfMonth($year$month$week$n) {
0193:     if ($n < 1)     return FALSE;
0194: 
0195:     $jd1 = Gregorian2JD($year$month, 1);
0196:     $wn1 = getWeekNumber($year$month, 1);
0197:     $dd  = $week - $wn1 < 0 ? 7 + $week - $wn1 : $week - $wn1;
0198:     $jd2 = $jd1 + $dd;
0199:     $jdn = $jd2 + 7 * ($n - 1);
0200:     list($yy$mm$dd) = JD2Gregorian($jdn);
0201: 
0202:     if ($mm != $month)   return FALSE;    //月のオーバーフロー
0203: 
0204:     return $dd;
0205: }
0206: 
0207: /**
0208:  * 移動祝日(ハッピーマンデー)であれば、その名称を取得する
0209:  * @param int $year  西暦年
0210:  * @param int $month 月
0211:  * @param int $day   日
0212:  * @param string lang jp=日本語名称/en=英語名称
0213:  * @return string 移動祝日の名称/FALSE=祝日ではない
0214: */
0215: function getMovableHoliday2($year$month$day$lang) {
0216: //移動祝日(ハッピーマンデー法)
0217: static $movable_holiday = array(
0218: //    月  曜日番号 第N曜日 開始年  終了年  名称
0219: array( 1, 1, 2, 2000, 9999, '成人の日', 'Coming of Age Day'),
0220: array( 7, 1, 3, 2003, 9999, '海の日',   'Marine Day'),
0221: array( 9, 1, 3, 2003, 9999, '敬老の日', 'Respect for the Aged Day'),
0222: array(10, 1, 2, 2000, 9999, '体育の日', 'Health and Sports Day')
0223: );
0224: 
0225:     $name = FALSE;
0226:     foreach ($movable_holiday as $val) {
0227:         if ($month == $val[0] && $day == getWeeksOfMonth($year$month$val[1]$val[2])) {
0228:             if ($year >= $val[3] && $year <= $val[4]) {
0229:                 $name = preg_match("/JP/i", $lang) == 1 ? $val[5] : $val[6];
0230:                 break;
0231:             }
0232:         }
0233:     }
0234:     return $name;
0235: }

いわゆるハッピーマンデー法で決まった祝日である。第2 月曜日または第3 月曜日が祝日に当たる。
space
ユーザー関数 getWeeksOfMonth は、ある月の第N 曜日を求めることができる。
将来、ハッピーフライデー法(笑)ができるかもしれないので、月曜日でなく、任意の曜日について求めることができるようにしてある。
space
ユーザー関数 getMovableHoliday2 は、ハッピーマンデーであれば、その名称を返す。getFixedHoliday と同様、祝日一覧を配列 $movable_holiday に用意しておく。今後、ハッピーマンデー法が変更になった場合は、この配列を変更するだけで対応できるようになっている。
この項つづく
header