サンプル・プログラムの実行例
目次
サンプル・プログラムのダウンロード
getHoliday.php | サンプル・プログラム本体。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
pahooCache.php | キャッシュ処理に関わるクラス pahooCache。 キャッシュ処理に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/02/25 | 内閣府の祝日表を参照できるようにした |
1.7.0 | 2023/10/14 | pahooInputDataクラス,Spinner導入 |
1.6 | 2021/04/24 | PHP8対応,リファラ・チェック改良 |
1.5 | 2020/01/02 | 暦計算クラスpahooCalendar使用 |
1.4 | 2019/07/13 | 土日もカウントできるようにした |
バージョン | 更新日 | 内容 |
---|---|---|
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
1.4.2 | 2024/01/28 | exitIfLessVersion() メッセージ修正 |
1.4.1 | 2023/09/30 | コメントの訂正 |
1.4.0 | 2023/09/09 | $_GET, $_POST参照をfilter_input()関数に置換 |
1.3.0 | 2023/07/11 | roundFloat() 追加 |
バージョン | 更新日 | 内容 |
---|---|---|
4.5.0 | 2024/03/17 | ヒジュラ暦メソッドを追加 |
4.4.1 | 2024/03/17 | getCabinetOfficeHolidayTable() -- bug-fix |
4.4.0 | 2024/02/25 | 内閣府の祝日表を参照できるようにした |
4.3.2 | 2023/02/11 | getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅 |
4.3.1 | 2023/02/03 | 表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン,七十二候 |
祝日法を整理する
なお、新天皇即位に伴う「天皇の退位等に関する皇室典範特例法」により2019年(平成31年)の祝日が、東京オリンピック開催にともなう「国民の祝日に関する法律の一部を改正する法律」により2020年(令和2年)の祝日が変更になっていることに留意する。
2020年(令和2年)1月現在の祝日を一覧にすると下記の通りである。
「開始年」は祝日が有効になった年を、「終了年」は祝日が有効な最後の年を示す。
月日 | 名称 | 開始年 | 終了年 | 備考 | |
日本語 | 英語 | ||||
固定祝日 | |||||
1月1日 | 元日 | New Year Day | 1949 | - | |
1月15日 | 成人の日 | Coming of Age Day | 1949 | 1999 | (※1) |
2月11日 | 建国記念の日 | National Foundation Day | 1967 | - | |
2月23日 | 天皇誕生日 | The Emperor's Birthday | 2020 | - | (※2) |
4月29日 | 天皇誕生日 | The Emperor's Birthday | 1949 | 1989 | (※2) |
4月29日 | みどりの日 | Greenery Day | 1990 | 2006 | (※2) |
4月29日 | 昭和の日 | Showa Day | 2007 | - | (※2) |
5月3日 | 憲法記念日 | Constitution Memorial Day | 1949 | - | |
5月4日 | 国民の休日 | Holiday for a Nation | 1988 | 2006 | (※3) |
5月4日 | みどりの日 | Greenery Day | 2007 | - | (※3) |
5月5日 | こどもの日 | Children's Day | 1949 | - | |
7月20日 | 海の日 | Marine Day | 1996 | 2002 | |
7月22日 | 海の日 | Marine Day | 2021 | 2021 | (※4) |
7月23日 | 海の日 | Marine Day | 2020 | 2020 | (※4) |
7月23日 | スポーツの日 | Sports Day | 2021 | 2021 | (※4) |
7月24日 | スポーツの日 | Sports Day | 2020 | 2020 | (※4) |
8月8日 | 山の日 | Mountain Day | 2021 | 2021 | (※4) |
8月11日 | 山の日 | Mountain Day | 2016 | 2019 | |
8月10日 | 山の日 | Mountain Day | 2020 | 2020 | (※4) |
8月11日 | 山の日 | Mountain Day | 2022 | - | |
9月15日 | 敬老の日 | Respect for the Aged Day | 1966 | 2002 | (※1) |
10月10日 | 体育の日 | Health and Sports Day | 1966 | 1999 | (※1) |
11月3日 | 文化の日 | National Culture Day | 1948 | - | |
11月23日 | 勤労感謝の日 | Labbor Thanksgiving Day | 1948 | - | |
12月23日 | 天皇誕生日 | The Emperor's Birthday | 1989 | 2018 | |
4月10日 | 皇太子明仁親王 の結婚の儀 |
The Rite of Wedding of HIH Crown Prince Akihito |
1959 | 1959 | (※4) |
2月24日 | 昭和天皇 の大喪の礼 |
The Funeral Ceremony of Emperor Showa. | 1989 | 1989 | (※4) |
11月12日 | 即位礼正殿の儀 | The Ceremony of the Enthronement of His Majesty the Emperor (at the Seiden) |
1990 | 1990 | (※4) |
6月9日 | 皇太子徳仁親王 の結婚の儀 |
The Rite of Wedding of HIH Crown Prince Naruhito |
1993 | 1993 | (※4) |
5月1日 | 即位の日 | Day of cadence | 2019 | 2019 | (※4) |
10月22日 | 即位礼正殿の儀 | The Ceremony of the Enthronement of His Majesty the Emperor (at the Seiden) |
2019 | 2019 | (※4) |
移動祝日1 | |||||
3月21日頃 | 春分の日 | Vernal Equinox Day | 1949 | - | |
9月23日頃 | 秋分の日 | Autumnal Equinox Day | 1948 | - | |
移動祝日2(いわゆるハッピーマンデー) | |||||
1月 第2月曜日 |
成人の日 | Coming of Age Day | 2000 | - | |
7月 第3月曜日 |
海の日 | Marine Day | 2003 | 2019 | |
7月 第3月曜日 |
海の日 | Marine Day | 2022 | - | |
9月 第3月曜日 |
敬老の日 | Respect for the Aged Day | 2003 | - | |
10月 第2月曜日 |
体育の日 | Health and Sports Day | 2000 | 2019 | |
10月 第2月曜日 |
スポーツの日 | Sports Day | 2022 | - | |
振替休日(holiday in lieu) | |||||
祝日が日曜にあたるときは、その翌日を休日とする。1973年4月12日から適用。 【改正】祝日が日曜にあたるときは、その日後において、その日に最も近い「国民の祝日」でない日を休日。2007年1月1日から適用。 |
|||||
国民の休日(Citizen's Holiday) | |||||
その前日及び翌日が「国民の祝日」である日(日曜日にあたる日及び前項に規定する休日にあたる日を除く。)は、休日とする。1985年12月27日から適用。 【改正】その前日及び翌日が「国民の祝日」である日(「国民の祝日」でない日に限る)は、休日とする。 2005年5月20日から適用。 |
(※1)2000年または2002年に「移動祝日2」となる。
(※2)1990年より「みどりの日」、2007年より「昭和の日」となる。
(※3)2007年より「みどりの日」となる。
(※4)1年だけの祝日
以下、それぞれのグループの計算方法を解説する。
解説:カレンダー計算
171: /**
172: * 指定した年がうるう年かどうかを判定する.
173: * 参考サイト https://www.pahoo.org/e-soul/webtech/php01/php05-01.shtm
174: * @param int $year 西暦年
175: * @return bool TRUE:閏年である/FALSE:平年である
176: */
177: function isleap($year) {
178: $ret = FALSE;
179: if ($year % 4 == 0) $ret = TRUE;
180: if ($year % 100 == 0) $ret = FALSE;
181: if ($year % 400 == 0) $ret = TRUE;
182: return $ret;
183: }
185: /**
186: * 指定した月の日数(月の最後の日)を返す.
187: * 参考サイト https://www.pahoo.org/e-soul/webtech/php01/php15-01.shtm
188: * @param int $year 西暦年
189: * @param int $month 月
190: * @return int 日数/FALSE:引数の異常
191: */
192: function getDaysInMonth($year, $month) {
193: static $days = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
194: if ($month < 1 || $month > 12) return FALSE;
195: $days[2] = $this->isleap($year) ? 29 : 28; //閏年の判定
196:
197: return $days[$month];
198: }
345: /**
346: * グレゴリオ暦(ローカル時間)からユリウス日を求める.
347: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
348: * @param int $year, $month, $day グレゴリオ暦による年月日
349: * @param float $hour, $min, $sec 時分秒(ローカル時間)(省略時は0)
350: * @param float $tdiff UTCとの時差;NULLの時はTDIFF(省略時はNULL)
351: * @return float ユリウス日
352: */
353: function Gregorian2JD($year, $month, $day, $hour=0, $min=0, $sec=0, $tdiff=NULL) {
354: //世界時との時差
355: if ($tdiff == NULL) {
356: $tdiff = $this->TDIFF;
357: }
358: $hour -= $tdiff;
359:
360: if ($month <= 2) {
361: $month += 12;
362: $year--;
363: }
364: $jd = floor(365.25 * $year) - floor($year / 100.0) + floor($year / 400.0);
365: $jd += floor(30.59 * ($month - 2.0)) + $day + 1721088.5;
366: $jd += $hour / 24.0 + $min / (24.0 * 60.0) + $sec / (24.0 * 60.0 * 60.0);
367:
368: return $jd;
369: }
426: /**
427: * ユリウス日からグレゴリオ暦(ローカル時間)を求める.
428: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
429: * @param float $jd ユリウス日
430: * @return array($year, $month, $day, $hour, $min, $sec) 西暦年月日
431: */
432: function JD2Gregorian($jd, $tdiff=NULL) {
433: //世界時との時差
434: if ($tdiff == NULL) {
435: $tdiff = $this->TDIFF;
436: }
437: $jd += ($tdiff / 24.0);
438:
439: $x0 = floor($jd + 68570);
440: $x1 = floor($x0 / 36524.25);
441: $x2 = $x0 - floor(36524.25 * $x1 + 0.75);
442: $x3 = floor(($x2 + 1) / 365.2425);
443: $x4 = $x2 - floor(365.25 * $x3) + 31;
444: $x5 = floor(floor($x4) / 30.59);
445: $x6 = floor(floor($x5) / 11.0);
446:
447: $day = $x4 - floor(30.59 * $x5);
448: $month = $x5 - 12 * $x6 + 2;
449: $year = 100 * ($x1 - 49) + $x3 + $x6;
450:
451: if ($month == 2 && $day > 28) {
452: $day = $this->isleap($year) ? 29 : 28;
453: }
454:
455: $tm = 86400 * ($jd - floor($jd));
456: $hour = floor($tm / 3600.0);
457: $min = floor(($tm - 3600 * $hour) / 60.0);
458: $sec = floor($tm - 3600 * $hour - 60 * $min);
459:
460: return array($year, $month, $day, $hour, $min, $sec);
461: }
258: /**
259: * 指定した年月日の曜日番号を求める.
260: * ツェラーの公式を用いる.曜日番号は0(日曜日)から開始する.
261: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
262: * @param int $year 西暦年
263: * @param int $month 月
264: * @param int $day 日
265: * @return int 曜日番号(0:日曜日, 1:月曜日...6:土曜日)
266: */
267: function getWeekNumber($year, $month, $day) {
268: if ($month <= 2) {
269: $month += 12;
270: $year--;
271: }
272: $c = floor($year / 100);
273: $y = $year % 100;
274: $t = -2 * $c + floor($c / 4);
275: $h = $day + floor(26 * ($month + 1) / 10) + $y + floor($y / 4) + $t - 1;
276: while ($h < 0) $h += 7; //Ver.3.1 bug-fix
277: $h = $h % 7;
278:
279: return $h;
280: }
しかし、date はUNIX 時間を基準にしているため、1970年(昭和45年)1月1日以降でないと使えない。今回は1948年(昭和23年)から対応しなければならないため、別のカレンダー関数を用意する必要がある。
PHPの環境によってはカレンダー関数が利用できる。
しかし、当サーバの環境では利用できないため、同様の関数を用意し、ユーザークラス "pahooCalendar" に分離している。まず、クラスファイル "pahooCalendar.php" を require_once し、オブジェクトを生成する。
指定した月の日数を返す関数として cal_days_in_month があるが、これも利用できないため、代わりにユーザー関数 getDaysInMonth を用意した。ある年が閏年かどうか判定する必要があるが、これについては「PHPで閏年かどうか判定する」で解説した通りである。
紀元前4713年1月1日からの通日をあらわす「ユリウス日」(Julian Day)というものがある。これであれば人類の有史時代全体を網羅できるので、天文学や歴史学で重宝されている。
ユーザー関数 Gregorian2JD は、西暦年月日からユリウス日を求める。JD2Gregorian は、ユリウス日から西暦年月日を求める。
getWeekNumber は、西暦年月日に対応する曜日番号を求める。曜日番号は、日曜日が0、月曜日が1‥‥土曜日が6である。
解説:固定祝日
2007: /**
2008: * 指定した年月日が固定祝日であれば,その名称を求める.
2009: * 祝日でなければFALSEを返す.
2010: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_getFixedHoliday
2011: * @param int $year 西暦年
2012: * @param int $month 月
2013: * @param int $day 日
2014: * @return string 固定祝日の名称/FALSE=祝日ではない
2015: */
2016: function getFixedHoliday($year, $month, $day) {
2017: //固定祝日
2018: static $fixed_holiday = array(
2019: // 月 日 開始年 終了年 名称
2020: array( 1, 1, 1949, 9999, '元日', "New Year's Day"),
2021: array( 1, 15, 1949, 1999, '成人の日', 'Coming of Age Day'),
2022: array( 2, 11, 1967, 9999, '建国記念の日', 'National Foundation Day'),
2023: array( 2, 23, 2020, 9999, '天皇誕生日', "The Emperor's Birthday"),
2024: array( 4, 29, 1949, 1989, '天皇誕生日', "The Emperor's Birthday"),
2025: array( 4, 29, 1990, 2006, 'みどりの日', 'Greenery Day'),
2026: array( 4, 29, 2007, 9999, '昭和の日', 'Showa Day'),
2027: array( 5, 3, 1949, 9999, '憲法記念日', 'Constitution Memorial Day'),
2028: array( 5, 4, 1988, 2006, '国民の休日', 'Holiday for a Nation'),
2029: array( 5, 4, 2007, 9999, 'みどりの日', 'Greenery Day'),
2030: array( 5, 5, 1949, 9999, 'こどもの日', "Children's Day"),
2031: array( 7, 20, 1996, 2002, '海の日', 'Marine Day'),
2032: array( 7, 22, 2021, 2021, '海の日', 'Marine Day'),
2033: array( 7, 23, 2020, 2020, '海の日', 'Marine Day'),
2034: array( 7, 23, 2021, 2021, 'スポーツの日', 'Health Sports Day'),
2035: array( 7, 24, 2020, 2020, 'スポーツの日', 'Health Sports Day'),
2036: array( 8, 8, 2021, 2021, '山の日', 'Mountain Day'),
2037: array( 8, 11, 2016, 2019, '山の日', 'Mountain Day'),
2038: array( 8, 10, 2020, 2020, '山の日', 'Mountain Day'),
2039: array( 8, 11, 2022, 9999, '山の日', 'Mountain Day'),
2040: array( 9, 15, 1966, 2002, '敬老の日', 'Respect for the Aged Day'),
2041: array(10, 10, 1966, 1999, '体育の日', 'Health and Sports Day'),
2042: array(11, 3, 1948, 9999, '文化の日', 'National Culture Day'),
2043: array(11, 23, 1948, 9999, '勤労感謝の日', 'Labbor Thanksgiving Day'),
2044: array(12, 23, 1989, 2018, '天皇誕生日', "The Emperor's Birthday"),
2045: //以下,1年だけの祝日
2046: array( 4, 10, 1959, 1959, '皇太子明仁親王の結婚の儀', "The Rite of Wedding of HIH Crown Prince Akihito"),
2047: array( 2, 24, 1989, 1989, '昭和天皇の大喪の礼', "The Funeral Ceremony of Emperor Showa."),
2048: array(11, 12, 1990, 1990, '即位礼正殿の儀', "The Ceremony of the Enthronement
2049: of His Majesty the Emperor (at the Seiden)"),
2050: array( 6, 9, 1993, 1993, '皇太子徳仁親王の結婚の儀 ', "The Rite of Wedding of HIH Crown Prince Naruhito"),
2051: array( 5, 1, 2019, 2019, '即位の日', 'Day of cadence'),
2052: array(10, 22, 2019, 2019, '即位礼正殿の儀', 'The Ceremony of the Enthronement of His Majesty the Emperor (at the Seiden)'),
2053: );
2054:
2055: $name = FALSE;
2056: foreach ($fixed_holiday as $val) {
2057: if ($month == $val[0] && $day == $val[1]) {
2058: if ($year >= $val[2] && $year <= $val[3]) {
2059: $name = preg_match('/jp/i', $this->language) == 1 ? $val[4] : $val[5];
2060: break;
2061: }
2062: }
2063: }
2064: return $name;
2065: }
1948年(昭和23年)に9つの祝日で始まった。ただし、7月20日に公布・施行だったため、7月19日以前の6つの祝日は翌1949年(昭和24年)から有効になった。
その後、東京オリンピックの翌年(1966年、昭和41年)に体育の日などが追加されていく。このときも6月25日に公布・施行だったため、建国記念の日(2月11日)は翌1967年(昭和42年)から有効になった。
その後、昭和天皇の崩御(1989年、昭和64年)に伴い、「天皇誕生日」の名称が目まぐるしく変わる。
また、いわゆるハッピーマンデー法の成立によって、2000年(平成12年)と2003年の二度にわたり、合計4つの祝日が移動した。
ユーザー関数 getFixedHoliday は、西暦年月日を与え、祝日であればその名称を返す。
プログラムは、まず、固定祝日の一覧を配列 $fixed_holiday に用意する。今後、固定祝日が変更になった場合は、この配列を変更するだけで対応できるようになっている。
そして、引数の月 $month と日 $day が合致するかどうかを調べる。
祝日の名称として、日本語と英語のいずれかを返すことができるようにしてある。
解説:移動祝日1(春分の日・秋分の日)
2067: /**
2068: * 内閣府の祝日表を読み込んでプロパティに代入する.
2069: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday1
2070: * @param なし
2071: * @return bool TRUE:成功/失敗(ファイルが見つからないなど)
2072: */
2073: function getCabinetOfficeHolidayTable() {
2074: if ($this->pcc == NULL) return FALSE;
2075:
2076: //内閣府の祝日表をキャッシュに読み込む
2077: $contents = $this->pcc->load(self::CABINETOFFICE_HOLIDAY_FILE);
2078: if ($contents == FALSE) return FALSE;
2079:
2080: //1行ずつ分解して解釈し、プロパティに代入する.
2081: $tok = strtok($contents, "\n");
2082: while ($tok !== FALSE) {
2083: $ss = mb_convert_encoding($tok, INTERNAL_ENCODING, 'SJIS');
2084: if (preg_match('/\s*([0-9]+)\s*\/\s*([0-9]+)\s*\/\s*([0-9]+)\s*\,(.+)/ui', $ss, $arr) > 0) {
2085: $year = (int)$arr[1];
2086: $mmdd = (string)sprintf('%02d%02d', $arr[2], $arr[3]);
2087: $holiday = (string)trim($arr[4]);
2088: $this->CabinetOfficeHolidayTables[$year][$holiday] = $mmdd;
2089: }
2090: $tok = strtok("\n");
2091: }
2092: return TRUE;
2093: }
2095: /**
2096: * 指定した年の春分の日を求める.
2097: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday1
2098: * @param int $year 西暦年
2099: * @param bool $cb TRUE:内閣の祝日表の日/FALSE:計算で求めた日
2100: * @return int 日(3月の)
2101: */
2102: function getVernalEquinox($year, &$cb=FALSE) {
2103: //内閣府の祝日表を読み込む
2104: if (count($this->CabinetOfficeHolidayTables) == 0) $this->getCabinetOfficeHolidayTable();
2105: //内閣府の祝日表にあれば
2106: if (isset($this->CabinetOfficeHolidayTables[$year]['春分の日'])) {
2107: $mmdd = $this->CabinetOfficeHolidayTables[$year]['春分の日'];
2108: $day = (int)substr($mmdd, 2, 2);
2109: $cb = TRUE;
2110:
2111: //計算で求める
2112: } else {
2113: $day = floor(20.8431 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
2114: $cb = FALSE;
2115: }
2116:
2117: return $day;
2118: }
2120: /**
2121: * 指定した年の秋分の日を求める.
2122: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday1
2123: * @param int $year 西暦年
2124: * @param bool $cb TRUE:内閣の祝日表の日/FALSE:計算で求めた日
2125: * @return int 日(9月の)
2126: */
2127: function getAutumnalEquinox($year, &$cb=FALSE) {
2128: //内閣府の祝日表を読み込む
2129: if (count($this->CabinetOfficeHolidayTables) == 0) $this->getCabinetOfficeHolidayTable();
2130: //内閣府の祝日表にあれば
2131: if (isset($this->CabinetOfficeHolidayTables[$year]['秋分の日'])) {
2132: $mmdd = $this->CabinetOfficeHolidayTables[$year]['秋分の日'];
2133: $day = (int)substr($mmdd, 2, 2);
2134: $cb = TRUE;
2135:
2136: //計算で求める
2137: } else {
2138: $day = floor(23.2488 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
2139: $cb = FALSE;
2140: }
2141:
2142: return $day;
2143: }
2145: /**
2146: * 指定した年月日が移動祝日(春分/秋分の日)であれば,その名称を求める.
2147: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday1
2148: * 移動祝日でなければFALSEを返す.
2149: * @param int $year 西暦年
2150: * @param int $month 月
2151: * @param int $day 日
2152: * @return string 移動祝日の名称/FALSE=祝日ではない
2153: */
2154: function getMovableHoliday1($year, $month, $day) {
2155: $name = FALSE;
2156:
2157: //春分の日
2158: $dd = $this->getVernalEquinox($year, $cb);
2159: if ($year >=1949 && $day == $dd && $month == 3) {
2160: $name = preg_match('/jp/i', $this->language) == 1 ? '春分の日' : 'Vernal Equinox Day';
2161: }
2162: //秋分の日
2163: $dd = $this->getAutumnalEquinox($year);
2164: if ($year >=1948 && $day == $dd && $month == 9) {
2165: $name = preg_match('/jp/i', $this->language) == 1 ? '秋分の日' : 'Autumnal Equinox Day';
2166: }
2167: return $name;
2168: }
秋分の日、秋分の日を天文学的な計算する手段はあるのだが、人為的に日付を変える可能性があるので、こればかりは計算で確定することができない。
一方、閣議決定された国民の祝日は、内閣府のページにCSVファイルとして公開されている。
そこで、このCSVファイルにあれば、その春分の日と秋分の日を返し、なければ計算によって求めることにする。
getVernalEquinox は、指定した年の春分の日を求めるメソッドである。
まず、プロパティ配列 $CabinetOfficeHolidayTables の要素が1つもなければ、getCabinetOfficeHolidayTable メソッドを使って、前述の内閣府のページにあるCSVファイルを読み込む。祝日表は頻繁に変わるものではないから、内閣府のページに余計な負荷を与えないように、いったん読み込んだCSVファイルはローカルにキャッシングするよう、キャッシュシステム pahooCache を利用する。
次に、プロパティ配列 $CabinetOfficeHolidayTables に指定した年の春分の日があれば、それを返し、無ければ、計算で求めた日を返す。計算で求める春分の日は、実際のカレンダーとは±1日程度ズレる可能性があることに留意されたい。
メソッドの第2引数 $cb は、祝日表から求めた日ならTRUEを、計算で求めたのならFALSEを代入する。呼び出し側で $cb を参照すれば、それが計算で求めたものかどうか判定できる。また、$cb は省略可能である。
getAutumnalEquinox は、指定した年の秋分の日を求めるメソッドである。流れは春分の日と同じである。
24: /**
25: * コンストラクタ
26: * @param string $language 表示言語;省略時 jp
27: * @param float $tdiff 世界時との時差(省略時 +9.0;日本標準時)
28: * @param object $pcc pahooCacheインスタンス;省略時 NULL
29: * インターネット経由で内閣府の国民の祝日を参照するときに指定
30: * @return bool オブジェクト/FALSE:$tdiffが不正
31: */
32: function __construct($language='jp', $tdiff=+9.0, $pcc=NULL) {
33: $this->error = FALSE;
34: $this->errmsg = '';
35: $this->year = date('Y');
36: $this->month = date('n');
37: $this->day = date('j');
38: $this->resolve2033 = 0;
39: $this->pcc = $pcc;
40: $this->CabinetOfficeHolidayTables = array();
41:
42: $this->setLanguage($language);
43: if ($this->setTimeDifference($tdiff) == FALSE) {
44: $this->error = TRUE;
45: $this->errmsg = 'illegal tdiff';
46: }
47: }
解説:移動祝日2(ハッピーマンデー)
2170: /**
2171: * ある月の第N曜日の日付を求める.
2172: * 計算オーバーフローが起きたらFALSEを返す.
2173: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday2
2174: * @param int $year 西暦年
2175: * @param int $month 月
2176: * @param int $week 曜日番号;0 (日曜)~ 6 (土曜)
2177: * @param int $n 第N曜日
2178: * @return int $day 日
2179: */
2180: function getWeeksOfMonth($year, $month, $week, $n) {
2181: if ($n < 1) return FALSE;
2182:
2183: $jd1 = $this->Gregorian2JD($year, $month, 1, 0, 0, 0, 0.0);
2184: $wn1 = $this->getWeekNumber($year, $month, 1);
2185: $dd = $week - $wn1 < 0 ? 7 + $week - $wn1 : $week - $wn1;
2186: $jd2 = $jd1 + $dd;
2187: $jdn = $jd2 + 7 * ($n - 1);
2188: list($yy, $mm, $dd) = $this->JD2Gregorian($jdn);
2189:
2190: if ($mm != $month) return FALSE; //月のオーバーフロー
2191:
2192: return $dd;
2193: }
2195: /**
2196: * 指定した年月日が移動祝日(ハッピーマンデー)であれば,その名称を求める.
2197: * 移動祝日でなければFALSEを返す.
2198: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_moving_holiday2
2199: * @param int $year 西暦年
2200: * @param int $month 月
2201: * @param int $day 日
2202: * @return string 移動祝日の名称/FALSE=祝日ではない
2203: */
2204: function getMovableHoliday2($year, $month, $day) {
2205: //移動祝日(ハッピーマンデー法)
2206: static $movable_holiday = array(
2207: // 月 曜日番号 第N曜日 開始年 終了年 名称
2208: array( 1, 1, 2, 2000, 9999, '成人の日', 'Coming of Age Day'),
2209: array( 7, 1, 3, 2003, 2019, '海の日', 'Marine Day'),
2210: array( 7, 1, 3, 2022, 9999, '海の日', 'Marine Day'),
2211: array( 9, 1, 3, 2003, 9999, '敬老の日', 'Respect for the Aged Day'),
2212: array(10, 1, 2, 2000, 2019, '体育の日', 'Health and Sports Day'),
2213: array(10, 1, 2, 2022, 9999, 'スポーツの日', 'Health Sports Day')
2214: );
2215:
2216: $name = FALSE;
2217: foreach ($movable_holiday as $val) {
2218: if ($month == $val[0] && $day == $this->getWeeksOfMonth($year, $month, $val[1], $val[2])) {
2219: if ($year >= $val[3] && $year <= $val[4]) {
2220: $name = preg_match('/jp/i', $this->language) == 1 ? $val[5] : $val[6];
2221: break;
2222: }
2223: }
2224: }
2225: return $name;
2226: }
ユーザー関数 getWeeksOfMonth は、ある月の第N曜日を求めることができる。
将来、ハッピーフライデー法(笑)ができるかもしれないので、月曜日でなく、任意の曜日について求めることができるようにしてある。
ユーザー関数 getMovableHoliday2 は、ハッピーマンデーであれば、その名称を返す。getFixedHoliday と同様、祝日一覧を配列 $movable_holiday に用意しておく。今後、ハッピーマンデー法が変更になった場合は、この配列を変更するだけで対応できるようになっている。
解説:振替休日
2243: /**
2244: * 指定した年月日が振替休日かどうかを求める.
2245: * 振替休日ならTRUEを返す.
2246: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_isTransferHoliday
2247: * @param int $year 西暦年
2248: * @param int $month 月
2249: * @param int $day 日
2250: * @return bool TRUE/FALSE
2251: */
2252: function isTransferHoliday($year, $month, $day) {
2253: $jd = $this->Gregorian2JD($year, $month, $day, 0, 0, 0);
2254: $j0 = $this->Gregorian2JD(1973, 4, 12, 0, 0, 0);
2255: if ($jd < $j0) return FALSE; //有効なのは1973年4月12日以降
2256:
2257: //当日が祝日なら FALSE
2258: if ($this->isFixedMovableHoliday($year, $month, $day)) return FALSE;
2259:
2260: $n = ($year <= 2006) ? 1 : 7; //改正法なら最大7日間遡る
2261: $jd--; //1日前
2262: for ($i = 0; $i < $n; $i++) { //無限ループに陥らないように
2263: list($yy, $mm, $dd) = $this->JD2Gregorian($jd);
2264: //祝日かつ日曜日なら振替休日
2265: if ($this->isFixedMovableHoliday($yy, $mm, $dd)
2266: && ($this->getWeekNumber($yy, $mm, $dd) == 0)) return TRUE;
2267: //祝日でなければ打ち切り
2268: if (! $this->isFixedMovableHoliday($yy, $mm, $dd)) break;
2269: $jd--; //1日前
2270: }
2271: return FALSE;
2272: }
ところがハッピーマンデー法が制定されてから以降は、日曜日、月曜日が連続して祝日になるケースが発生する。そこで、2007年(平成19年)1月以降は、
祝日が日曜にあたるときは、その日後において、その日に最も近い「国民の祝日」でない日を休日とすることになった。前述の場合は火曜日が祝日になる。
とくに2009年(平成21年)は、5月3日の日曜日が憲法記念日、月曜日のみどりの日、火曜日のこどもの日と、祝日が3日連続することになった。この場合は水曜日が振替休日となる。
ユーザー関数 isTransferHoliday は、与えられた西暦年月日が振替休日かどうか調べるものである。
前日が祝日である場合は、for ループを用い、日曜日まで祝日が続いているかどうか遡ってチェックするようにしている。連続していれば、その日は振替休日である。
ここで while ではなくforループを用いたのは、引数や他の祝日判定の異常で無限ループに陥ることがないようにするための配慮である。
解説:国民の休日
2274: /**
2275: * 指定した年月日が国民の休日かどうかを求める.
2276: * 国民の休日ならTRUEを返す.
2277: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_isNationalHoliday
2278: * @param int $year 西暦年
2279: * @param int $month 月
2280: * @param int $day 日
2281: * @return bool TRUE/FALSE
2282: */
2283: function isNationalHoliday($year, $month, $day) {
2284: if ($year < 2003) return FALSE; //有効なのは2003年以降
2285: $j0 = $this->Gregorian2JD($year, $month, $day, 0, 0, 0) - 1; //前日
2286: list($yy0, $mm0, $dd0) = $this->JD2Gregorian($j0);
2287: $j1 = $this->Gregorian2JD($year, $month, $day, 0, 0, 0) + 1; //翌日
2288: list($yy1, $mm1, $dd1) = $this->JD2Gregorian($j1);
2289:
2290: //前日と翌日が固定祝日または移動祝日なら国民の休日
2291: if ($this->isFixedMovableHoliday($yy0, $mm0, $dd0)
2292: && $this->isFixedMovableHoliday($yy1, $mm1, $dd1)) return TRUE;
2293: return FALSE;
2294: }
ユーザー関数 isTransferHoliday は、与えられた西暦年月日が国民の休日かどうかを調べる。
その翌日と前日が、固定祝日、移動祝日1、移動祝日2のいずれかでないかどうかを調べているだけである。
解説:祝日を求める
2296: /**
2297: * 指定した年月日が祝日であれば,その名称を求める.
2298: * 祝日でなければFALSEを返す.
2299: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_getHoliday
2300: * @param int $year 西暦年
2301: * @param int $month 月
2302: * @param int $day 日
2303: * @return string 祝日の名称/FALSE=祝日ではない
2304: */
2305: function getHoliday($year, $month, $day) {
2306: //固定祝日
2307: $name = $this->getFixedHoliday($year, $month, $day, 'jp');
2308: if ($name != FALSE) return $name;
2309: //移動祝日(春分/秋分の日)
2310: $name = $this->getMovableHoliday1($year, $month, $day, 'jp');
2311: if ($name != FALSE) return $name;
2312: //移動祝日(ハッピーマンデー)
2313: $name = $this->getMovableHoliday2($year, $month, $day, 'jp');
2314: if ($name != FALSE) return $name;
2315: //振替休日
2316: if ($this->isTransferHoliday($year, $month, $day)) {
2317: return preg_match('/jp/i', $this->language) == 1 ? '振替休日' : 'holiday in lieu';
2318: }
2319: //国民の祝日
2320: if ($this->isNationalHoliday($year, $month, $day)) {
2321: return preg_match('/jp/i', $this->language) == 1 ? '国民の休日' : "Citizen's Holiday";
2322: }
2323: //祝日ではない
2324: return FALSE;
2325: }
2327: /**
2328: * 指定した年月日が祝日かどうかを求める.
2329: * 祝日ならTRUEを返す.
2330: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm#php_getHoliday
2331: * @param int $year 西暦年
2332: * @param int $month 月
2333: * @param int $day 日
2334: * @return bool TRUE/FALSE
2335: */
2336: function isHoliday($year, $month, $day) {
2337: return getHoliday($year, $month, $day, 'jp') == FALSE ? FALSE : TRUE;
2338: }
固定祝日、移動祝日1、移動祝日2、振替休日、国民の休日を順々に調べている。
ユーザー関数 isHoliday は、与えられた西暦年月日が祝日かどうかを調べるものである。
以上の関数を利用し、入力された西暦年から以降3年分の祝日一覧を表示するのがサンプル・プログラムである。
祝日と祭日
戦後、GHQの占領下において、神道に基づく儀礼は一切廃止されたため、「祭日」は無くなった。そして、国民が祝うべき「祝日」に切り替わったのである。
ところが実際は、新憲法が制定された1947年(昭和22年)を過ぎても戦前の祝日法が有効であり、ようやく1948年(昭和23年)になって新しい「国民の祝日に関する法律」(祝日法)が定められた。
「『国民の祝日』の由来がわかる小事典」(所功/PHP研究所/2003年(平成15年)08月)は、祝日を
- 祭日に基づく祝日
- 国家にちなむ祝日
- 人生に伴う祝日
参考書籍
知れば知るほど面白い暦の謎 | |||
著者 | 片山 真人 | ||
出版社 | 三笠書房 | ||
サイズ | 文庫 | ||
発売日 | 2022年02月17日頃 | ||
価格 | 858円(税込) | ||
ISBN | 9784837987635 | ||
1週間はなぜ「7日」なのか?「曜日」はどのように生まれたか?国立天文台「暦の専門家」が教える! | |||
理科年表Q&A | |||
著者 | 理科年表Q&A編集委員会 | ||
出版社 | 丸善出版 | ||
サイズ | 単行本 | ||
発売日 | 2003年11月 | ||
価格 | 1,980円(税込) | ||
ISBN | 9784621073360 | ||
本書では、これまで理科年表編集部が受けたたくさんの質問の中から、「これはなるほど」、「これは知って便利」というテーマを選び出し、理科年表の部門「暦(こよみ)」、「天文」、「気象」、「物理/化学」、「地学」、「生物」に沿ってしぼり込み、できるだけわかりやすく解説しながら答えを書くよう努めました。 | |||
暦の雑学事典 | |||
著者 | 吉岡安之 | ||
出版社 | 日本実業出版社 | ||
サイズ | 単行本 | ||
発売日 | 1999年12月 | ||
価格 | 1,430円(税込) | ||
ISBN | 9784534030214 | ||
知っているとちょっと楽しい知識を満載!ミレニアムの意外な秘密がわかる。暦の歴史をたどり、ルーツを探る。いまに生きる旧暦の数々がわかる。さまざまな時計の歴史と科学を紹介。身近な暦の話題から歳時記まで暦の蘊蓄が盛りだくさん。 | |||
「国民の祝日」の由来がわかる小事典 | |||
著者 | 所功 | ||
出版社 | PHP研究所 | ||
サイズ | 新書 | ||
発売日 | 2003年08月 | ||
価格 | 858円(税込) | ||
ISBN | 9784569630861 | ||
「建国記念日の日」「こどもの日」「勤労感謝の日」…。今や年間十五日にのぼる「国民の祝日」はいつ頃、どのように成立したのか。古来の民俗的な年中行事や人生儀礼に伴なう祝祭日。明治以降の国家的な祝日。さらに平成に入ってから付け加えられた「みどりの日」や「海の日」など、「国民の祝日」は古さと新しさをあわせもつ。そこには、わが国で永年育まれてきた自然と、先祖に感謝する心、共同体の人間関係を尊ぶ豊かな精神が盛り込まれている。歴史学の観点から日本人の英知を解き明かす。 | |||
プログラミングのセオリー | |||
著者 | 矢沢久雄 | ||
出版社 | 技術評論社 | ||
サイズ | 単行本 | ||
発売日 | 2008年11月 | ||
価格 | 2,618円(税込) | ||
ISBN | 9784774136288 | ||
参考サイト
- PHPで閏年かどうか判定する:ぱふぅ家のホームページ
- PHPで万年カレンダーを作る:ぱふぅ家のホームページ
- 秋分の日と敬老の日の微妙な関係:ぱふぅ家のホームページ
- 暦要項:国立天文台
- 国民の祝日について:内閣府
- 知ってそうで知らない「国民の祝日」とその趣旨や経緯:政府広報オンライン
あらかじめ断っておくが、計算によって祝日を求めることは難しい。
「秋分の日と敬老の日の微妙な関係」で述べたように、法律によって祝日が変わるなどのルールがあるため、ある年の祝日を計算で完全に求めることはできない。
過去の祝日であれば、実際のカレンダーから祝日を抜き出してテーブルに用意しておき、それを引いた方が確実である。また、未来の祝日についても、アプリケーションやインターネットにあるものをテーブルとして取り込み、それを引いた方が手っ取り早く確実である。
ここでは、アプリケーションやインターネットにないような未来の祝日を求めることを目的に、あえて計算で導出することを考えてみることにする。
(2024年2月25日)内閣府の祝日表を参照できるようにした.とくに春分の日・秋分の日.
(2023年10月14日)pahooInputDataクラス,Spinner導入.