PHPで祝日を求める

(2/4)

サンプル・プログラムの解説:カレンダー計算

0017: /**
0018:  * 閏年かどうか判定する
0019:  * @param int $year 西暦年
0020:  * @return bool TRUE:閏年である/FALSE:平年である
0021: */
0022: function isleap($year) {
0023:     $ret = FALSE;
0024:     if ($year % 4 == 0)     $ret = TRUE;
0025:     if ($year % 100 == 0)   $ret = FALSE;
0026:     if ($year % 400 == 0)   $ret = TRUE;
0027:     return $ret;
0028: }
0029: 
0030: /**
0031:  * 指定した月の日数を返す
0032:  * @param int $year  西暦年
0033:  * @param int $month 月
0034:  * @return int 日数/FALSE:引数の異常
0035: */
0036: function getDaysInMonth($year$month) {
0037:     static $days = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
0038:     if ($month < 1 || $month > 12)  return FALSE;
0039:     $days[2] = isleap($year) ? 29 : 28;       //閏年の判定
0040: 
0041:     return $days[$month];
0042: }
0043: 
0044: /**
0045:  * グレゴリオ暦⇒ユリウス日 変換
0046:  * @param int $year  西暦年
0047:  * @param int $month 月
0048:  * @param int $day   日
0049:  * @return double ユリウス日(JD)
0050: */
0051: function Gregorian2JD($year$month$day) {
0052:     if ($month <= 2) {
0053:         $month += 12;
0054:         $year--;
0055:     }
0056:     return floor(365.25 * $year) - floor($year / 100) + floor($year / 400) + floor(30.6001 * ($month + 1)) + $day +1720996.5;
0057: }
0058: 
0059: /**
0060:  * ユリウス日⇒グレゴリオ暦 変換
0061:  * @param double $jd ユリウス日
0062:  * @return array($year, $month, $day)  西暦年月日
0063: */
0064: function JD2Gregorian($jd) {
0065:     $jd += 0.5;
0066:     $z = floor($jd);
0067:     $f = $jd - $z;
0068:     $aa = floor(($z - 1867216.25) / 36524.25);
0069:     $a = floor($z + 1 + $aa - floor($aa / 4));
0070:     $b = $a + 1524;
0071:     $c = floor(($b - 122.1) / 365.25);
0072:     $k = floor(365.25 * $c);
0073:     $e = floor(($b - $k) / 30.6001);
0074: 
0075:     $day = floor($b - $k - floor(30.6001 * $e));
0076:     $month = ($e < 13.5) ? ($e - 1) : ($e - 13);
0077:     $year = ($month > 2.5) ? ($c - 4716) : ($c - 4715);
0078: 
0079:     return array($year$month$day);
0080: }
0081: 
0082: /**
0083:  * 曜日番号を求める
0084:  * @param int $year  西暦年
0085:  * @param int $month 月
0086:  * @param int $day   日
0087:  * @return int 曜日番号(0:日曜日, 1:月曜日...6:土曜日)
0088: */
0089: function getWeekNumber($year$month$day) {
0090:     $jd = Gregorian2JD($year$month$day);
0091:     return ($jd + 1.5) % 7;
0092: }

PHP には曜日などの計算を行うための関数として  data  が用意されている。
しかし、date はUNIX 時間を基準にしているため、1970 年 1 月 1 日以降でないと使えない。今回は 1948 年から対応しなければならないため、別のカレンダー関数を用意する必要がある。
space
PHP の環境によってはカレンダー関数が利用できる。
しかし、当サーバの環境では利用できないため、同様の関数を用意することにした。
space
指定した月の日数を返す関数として  cal_days_in_month  があるが、これも利用できないため、代わりにユーザー関数 getDaysInMonth を用意した。ある年が閏年(うるう年)かどうか判定する必要があるが、これについては「PHP で閏年かどうか判定する」で解説した通りである。
space
紀元前 4713 年 1 月 1 日からの通日をあらわす「ユリウス日」(Julian Day)というものがある。これであれば人類の有史時代全体を網羅できるので、天文学や歴史学で重宝されている。
ユーザー関数 Gregorian2JD は、西暦年月日からユリウス日を求める。JD2Gregorian は、ユリウス日から西暦年月日を求める。
getWeekNumber は、西暦年月日に対応する曜日番号を求める。曜日番号は、日曜日が 0、月曜日が 1‥‥土曜日が 6 である。
space

サンプル・プログラムの解説:固定祝日

0094: /**
0095:  * 固定祝日であれば、その名称を取得する
0096:  * @param int $year  西暦年
0097:  * @param int $month 月
0098:  * @param int $day   日
0099:  * @param string lang jp=日本語名称/en=英語名称
0100:  * @return string 固定祝日の名称/FALSE=祝日ではない
0101: */
0102: function getFixedHoliday($year$month$day$lang) {
0103: //固定祝日
0104: static $fixed_holiday = array(
0105: //    月  日  開始年 終了年  名称
0106: array( 1,  1, 1949, 9999, '元日',         "New Year's Day"),
0107: array( 1, 15, 1949, 1999, '成人の日',     'Coming of Age Day'),
0108: array2, 11, 1967, 9999, '建国記念の日', 'National Foundation Day'),
0109: array( 4, 29, 1949, 1989, '天皇誕生日',   "The Emperor's Birthday"),
0110: array( 4, 29, 1990, 2006, 'みどりの日',   'Greenery Day'),
0111: array( 4, 29, 2007, 9999, '昭和の日',     'Showa Day'),
0112: array( 5,  3, 1949, 9999, '憲法記念日',   'Constitution Memorial Day'),
0113: array( 5,  4, 1988, 2006, '国民の休日',   'Holiday for a Nation'),
0114: array( 5,  4, 2007, 9999, 'みどりの日',   'Greenery Day'),
0115: array( 5,  5, 1949, 9999, 'こどもの日',   "Children's Day"),
0116: array( 7, 20, 1996, 2002, '海の日',       'Marine Day'),
0117: array( 9, 15, 1966, 2002, '敬老の日',     'Respect for the Aged Day'),
0118: array(10, 10, 1966, 1999, '体育の日',     'Health and Sports Day'),
0119: array(11,  3, 1948, 9999, '文化の日',     'National Culture Day'),
0120: array(11, 23, 1948, 9999, '勤労感謝の日', 'Labbor Thanksgiving Day'),
0121: array(12, 23, 1989, 9999, '天皇誕生日',   "The Emperor's Birthday"),
0122: //以下、1年だけの祝日
0123: array( 4, 10, 1959, 1959, '皇太子明仁親王の結婚の儀', "The Rite of Wedding of HIH Crown Prince Akihito"),
0124: array2, 24, 1989, 1989, '昭和天皇の大喪の礼', "The Funeral Ceremony of Emperor Showa."),
0125: array(11, 12, 1990, 1990, '即位礼正殿の儀', "The Ceremony of the Enthronement
0126:       of His Majesty the Emperor (at the Seiden)
"),
0127: array( 6,  9, 1993, 1993, '皇太子徳仁親王の結婚の儀 ', "The Rite of Wedding of HIH Crown Prince Naruhito")
0128: );
0129: 
0130:     $name = FALSE;
0131:     foreach ($fixed_holiday as $val) {
0132:         if ($month == $val[0] && $day == $val[1]) {
0133:             if ($year >= $val[2] && $year <= $val[3]) {
0134:                 $name = preg_match("/JP/i", $lang) == 1 ? $val[4] : $val[5];
0135:                 break;
0136:             }
0137:         }
0138:     }
0139:     return $name;
0140: }

毎年月日が決まっている祝日である。
1948 年(昭和 23 年)に 9 つの祝日で始まった。ただし、7 月 20 日に公布・施行だったため、7 月 19 日以前の 6 つの祝日は翌1949 年から有効になった。
その後、東京オリンピックの翌年(1966 年、昭和 41 年)に体育の日などが追加されていく。このときも 6 月 25 日に公布・施行だったため、建国記念の日(2 月 11 日)は翌1967 年から有効になった。
その後、昭和天皇の崩御(1989 年、昭和 64 年)に伴い、「天皇誕生日」の名称が目まぐるしく変わる。
また、いわゆるハッピーマンデー法の成立によって、2000 年(平成 14 年)と 2003 年(平成 17 年)の二度にわたり、合計4 つの祝日が移動した。
space
ユーザー関数 getFixedHoliday は、西暦年月日を与え、祝日であればその名称を返す。
プログラムは、まず、固定祝日の一覧を配列 $fixed_holiday に用意する。今後、固定祝日が変更になった場合は、この配列を変更するだけで対応できるようになっている。
そして、引数の月 $month と日 $day が合致するかどうかを調べる。
祝日の名称として、日本語と英語のいずれかを返すことができるようにしてある。
space
この項つづく
header