サンプル・プログラムの実行例

目次
サンプル・プログラムのダウンロード
getHoliday.php | サンプル・プログラム本体。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
祝日法を整理する
なお、新天皇即位に伴う「天皇の退位等に関する皇室典範特例法」により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年だけの祝日
以下、それぞれのグループの計算方法を解説する。
解説:カレンダー計算
163: /**
164: * 指定した年がうるう年かどうかを判定する.
165: * 参考サイト https://www.pahoo.org/e-soul/webtech/php01/php05-01.shtm
166: * @param int $year 西暦年
167: * @return bool TRUE:閏年である/FALSE:平年である
168: */
169: function isleap($year) {
170: $ret = FALSE;
171: if ($year % 4 == 0) $ret = TRUE;
172: if ($year % 100 == 0) $ret = FALSE;
173: if ($year % 400 == 0) $ret = TRUE;
174: return $ret;
175: }
177: /**
178: * 指定した月の日数(月の最後の日)を返す.
179: * 参考サイト https://www.pahoo.org/e-soul/webtech/php01/php15-01.shtm
180: * @param int $year 西暦年
181: * @param int $month 月
182: * @return int 日数/FALSE:引数の異常
183: */
184: function getDaysInMonth($year, $month) {
185: static $days = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
186: if ($month < 1 || $month > 12) return FALSE;
187: $days[2] = $this->isleap($year) ? 29 : 28; //閏年の判定
188:
189: return $days[$month];
190: }
337: /**
338: * グレゴリオ暦(ローカル時間)からユリウス日を求める.
339: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
340: * @param int $year, $month, $day グレゴリオ暦による年月日
341: * @param float $hour, $min, $sec 時分秒(ローカル時間)(省略時は0)
342: * @param float $tdiff UTCとの時差;NULLの時はTDIFF(省略時はNULL)
343: * @return float ユリウス日
344: */
345: function Gregorian2JD($year, $month, $day, $hour=0, $min=0, $sec=0, $tdiff=NULL) {
346: //世界時との時差
347: if ($tdiff == NULL) {
348: $tdiff = $this->TDIFF;
349: }
350: $hour -= $tdiff;
351:
352: if ($month <= 2) {
353: $month += 12;
354: $year--;
355: }
356: $jd = floor(365.25 * $year) - floor($year / 100.0) + floor($year / 400.0);
357: $jd += floor(30.59 * ($month - 2.0)) + $day + 1721088.5;
358: $jd += $hour / 24.0 + $min / (24.0 * 60.0) + $sec / (24.0 * 60.0 * 60.0);
359:
360: return $jd;
361: }
418: /**
419: * ユリウス日からグレゴリオ暦(ローカル時間)を求める.
420: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
421: * @param float $jd ユリウス日
422: * @return array($year, $month, $day, $hour, $min, $sec) 西暦年月日
423: */
424: function JD2Gregorian($jd, $tdiff=NULL) {
425: //世界時との時差
426: if ($tdiff == NULL) {
427: $tdiff = $this->TDIFF;
428: }
429: $jd += ($tdiff / 24.0);
430:
431: $x0 = floor($jd + 68570);
432: $x1 = floor($x0 / 36524.25);
433: $x2 = $x0 - floor(36524.25 * $x1 + 0.75);
434: $x3 = floor(($x2 + 1) / 365.2425);
435: $x4 = $x2 - floor(365.25 * $x3) + 31;
436: $x5 = floor(floor($x4) / 30.59);
437: $x6 = floor(floor($x5) / 11.0);
438:
439: $day = $x4 - floor(30.59 * $x5);
440: $month = $x5 - 12 * $x6 + 2;
441: $year = 100 * ($x1 - 49) + $x3 + $x6;
442:
443: if ($month == 2 && $day > 28) {
444: $day = $this->isleap($year) ? 29 : 28;
445: }
446:
447: $tm = 86400 * ($jd - floor($jd));
448: $hour = floor($tm / 3600.0);
449: $min = floor(($tm - 3600 * $hour) / 60.0);
450: $sec = floor($tm - 3600 * $hour - 60 * $min);
451:
452: return array($year, $month, $day, $hour, $min, $sec);
453: }
250: /**
251: * 指定した年月日の曜日番号を求める.
252: * ツェラーの公式を用いる.曜日番号は0(日曜日)から開始する.
253: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-27-01.shtm
254: * @param int $year 西暦年
255: * @param int $month 月
256: * @param int $day 日
257: * @return int 曜日番号(0:日曜日, 1:月曜日...6:土曜日)
258: */
259: function getWeekNumber($year, $month, $day) {
260: if ($month <= 2) {
261: $month += 12;
262: $year--;
263: }
264: $c = floor($year / 100);
265: $y = $year % 100;
266: $t = -2 * $c + floor($c / 4);
267: $h = $day + floor(26 * ($month + 1) / 10) + $y + floor($y / 4) + $t - 1;
268: while ($h < 0) $h += 7; //Ver.3.1 bug-fix
269: $h = $h % 7;
270:
271: return $h;
272: }
しかし、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である。
解説:固定祝日
1940: /**
1941: * 指定した年月日が固定祝日であれば,その名称を求める.
1942: * 祝日でなければFALSEを返す.
1943: * @param int $year 西暦年
1944: * @param int $month 月
1945: * @param int $day 日
1946: * @return string 固定祝日の名称/FALSE=祝日ではない
1947: */
1948: function getFixedHoliday($year, $month, $day) {
1949: //固定祝日
1950: static $fixed_holiday = array(
1951: // 月 日 開始年 終了年 名称
1952: array( 1, 1, 1949, 9999, '元日', "New Year's Day"),
1953: array( 1, 15, 1949, 1999, '成人の日', 'Coming of Age Day'),
1954: array( 2, 11, 1967, 9999, '建国記念の日', 'National Foundation Day'),
1955: array( 2, 23, 2020, 9999, '天皇誕生日', "The Emperor's Birthday"),
1956: array( 4, 29, 1949, 1989, '天皇誕生日', "The Emperor's Birthday"),
1957: array( 4, 29, 1990, 2006, 'みどりの日', 'Greenery Day'),
1958: array( 4, 29, 2007, 9999, '昭和の日', 'Showa Day'),
1959: array( 5, 3, 1949, 9999, '憲法記念日', 'Constitution Memorial Day'),
1960: array( 5, 4, 1988, 2006, '国民の休日', 'Holiday for a Nation'),
1961: array( 5, 4, 2007, 9999, 'みどりの日', 'Greenery Day'),
1962: array( 5, 5, 1949, 9999, 'こどもの日', "Children's Day"),
1963: array( 7, 20, 1996, 2002, '海の日', 'Marine Day'),
1964: array( 7, 22, 2021, 2021, '海の日', 'Marine Day'),
1965: array( 7, 23, 2020, 2020, '海の日', 'Marine Day'),
1966: array( 7, 23, 2021, 2021, 'スポーツの日', 'Health Sports Day'),
1967: array( 7, 24, 2020, 2020, 'スポーツの日', 'Health Sports Day'),
1968: array( 8, 8, 2021, 2021, '山の日', 'Mountain Day'),
1969: array( 8, 11, 2016, 2019, '山の日', 'Mountain Day'),
1970: array( 8, 10, 2020, 2020, '山の日', 'Mountain Day'),
1971: array( 8, 11, 2022, 9999, '山の日', 'Mountain Day'),
1972: array( 9, 15, 1966, 2002, '敬老の日', 'Respect for the Aged Day'),
1973: array(10, 10, 1966, 1999, '体育の日', 'Health and Sports Day'),
1974: array(11, 3, 1948, 9999, '文化の日', 'National Culture Day'),
1975: array(11, 23, 1948, 9999, '勤労感謝の日', 'Labbor Thanksgiving Day'),
1976: array(12, 23, 1989, 2018, '天皇誕生日', "The Emperor's Birthday"),
1977: //以下,1年だけの祝日
1978: array( 4, 10, 1959, 1959, '皇太子明仁親王の結婚の儀', "The Rite of Wedding of HIH Crown Prince Akihito"),
1979: array( 2, 24, 1989, 1989, '昭和天皇の大喪の礼', "The Funeral Ceremony of Emperor Showa."),
1980: array(11, 12, 1990, 1990, '即位礼正殿の儀', "The Ceremony of the Enthronement
1981: of His Majesty the Emperor (at the Seiden)"),
1982: array( 6, 9, 1993, 1993, '皇太子徳仁親王の結婚の儀 ', "The Rite of Wedding of HIH Crown Prince Naruhito"),
1983: array( 5, 1, 2019, 2019, '即位の日', 'Day of cadence'),
1984: array(10, 22, 2019, 2019, '即位礼正殿の儀', 'The Ceremony of the Enthronement of His Majesty the Emperor (at the Seiden)'),
1985: );
1986:
1987: $name = FALSE;
1988: foreach ($fixed_holiday as $val) {
1989: if ($month == $val[0] && $day == $val[1]) {
1990: if ($year >= $val[2] && $year <= $val[3]) {
1991: $name = preg_match('/jp/i', $this->language) == 1 ? $val[4] : $val[5];
1992: break;
1993: }
1994: }
1995: }
1996: return $name;
1997: }
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
1999: /**
2000: * 指定した年の春分の日を求める.
2001: * @param int $year 西暦年
2002: * @return int 日(3月の)
2003: */
2004: function getVernalEquinox($year) {
2005: return floor(20.8431 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
2006: }
2008: /**
2009: * 指定した年の秋分の日を求める.
2010: * @param int $year 西暦年
2011: * @return int 日(9月の)
2012: */
2013: function getAutumnalEquinox($year) {
2014: return floor(23.2488 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4));
2015: }
2017: /**
2018: * 指定した年月日が移動祝日(春分/秋分の日)であれば,その名称を求める.
2019: * 移動祝日でなければFALSEを返す.
2020: * @param int $year 西暦年
2021: * @param int $month 月
2022: * @param int $day 日
2023: * @return string 移動祝日の名称/FALSE=祝日ではない
2024: */
2025: function getMovableHoliday1($year, $month, $day) {
2026: $name = FALSE;
2027:
2028: //春分の日
2029: $dd = $this->getVernalEquinox($year);
2030: if ($year >=1949 && $day == $dd && $month == 3) {
2031: $name = preg_match('/jp/i', $this->language) == 1 ? '春分の日' : 'Vernal Equinox Day';
2032: }
2033: //秋分の日
2034: $dd = $this->getAutumnalEquinox($year);
2035: if ($year >=1948 && $day == $dd && $month == 9) {
2036: $name = preg_match('/jp/i', $this->language) == 1 ? '秋分の日' : 'Autumnal Equinox Day';
2037: }
2038: return $name;
2039: }
秋分の日、秋分の日を天文学的な計算する手段はあるのだが、人為的に日付を変える可能性があるので、こればかりは計算で確実に求めることができない。

ユーザー関数 getVernalEquinox は天文学的に春分の日を、getAutumnalEquinox は秋分の日を計算するものである。
あくまで計算で求めているので、実際のカレンダーとは±1日程度ズレる可能性があることに留意されたい。すでにカレンダーとして決まっている2009年(平成21年)以前の春分の日、秋分の日も計算によって求めているので、過去のカレンダーと合致しないかもしれない。
解説:移動祝日2
2041: /**
2042: * ある月の第N曜日の日付を求める.
2043: * 計算オーバーフローが起きたらFALSEを返す.
2044: * @param int $year 西暦年
2045: * @param int $month 月
2046: * @param int $week 曜日番号;0 (日曜)~ 6 (土曜)
2047: * @param int $n 第N曜日
2048: * @return int $day 日
2049: */
2050: function getWeeksOfMonth($year, $month, $week, $n) {
2051: if ($n < 1) return FALSE;
2052:
2053: $jd1 = $this->Gregorian2JD($year, $month, 1, 0, 0, 0, 0.0);
2054: $wn1 = $this->getWeekNumber($year, $month, 1);
2055: $dd = $week - $wn1 < 0 ? 7 + $week - $wn1 : $week - $wn1;
2056: $jd2 = $jd1 + $dd;
2057: $jdn = $jd2 + 7 * ($n - 1);
2058: list($yy, $mm, $dd) = $this->JD2Gregorian($jdn);
2059:
2060: if ($mm != $month) return FALSE; //月のオーバーフロー
2061:
2062: return $dd;
2063: }
2065: /**
2066: * 指定した年月日が移動祝日(ハッピーマンデー)であれば,その名称を求める.
2067: * 移動祝日でなければFALSEを返す.
2068: * @param int $year 西暦年
2069: * @param int $month 月
2070: * @param int $day 日
2071: * @return string 移動祝日の名称/FALSE=祝日ではない
2072: */
2073: function getMovableHoliday2($year, $month, $day) {
2074: //移動祝日(ハッピーマンデー法)
2075: static $movable_holiday = array(
2076: // 月 曜日番号 第N曜日 開始年 終了年 名称
2077: array( 1, 1, 2, 2000, 9999, '成人の日', 'Coming of Age Day'),
2078: array( 7, 1, 3, 2003, 2019, '海の日', 'Marine Day'),
2079: array( 7, 1, 3, 2022, 9999, '海の日', 'Marine Day'),
2080: array( 9, 1, 3, 2003, 9999, '敬老の日', 'Respect for the Aged Day'),
2081: array(10, 1, 2, 2000, 2019, '体育の日', 'Health and Sports Day'),
2082: array(10, 1, 2, 2022, 9999, 'スポーツの日', 'Health Sports Day')
2083: );
2084:
2085: $name = FALSE;
2086: foreach ($movable_holiday as $val) {
2087: if ($month == $val[0] && $day == $this->getWeeksOfMonth($year, $month, $val[1], $val[2])) {
2088: if ($year >= $val[3] && $year <= $val[4]) {
2089: $name = preg_match('/jp/i', $this->language) == 1 ? $val[5] : $val[6];
2090: break;
2091: }
2092: }
2093: }
2094: return $name;
2095: }

ユーザー関数 getWeeksOfMonth は、ある月の第N曜日を求めることができる。
将来、ハッピーフライデー法(笑)ができるかもしれないので、月曜日でなく、任意の曜日について求めることができるようにしてある。

ユーザー関数 getMovableHoliday2 は、ハッピーマンデーであれば、その名称を返す。getFixedHoliday と同様、祝日一覧を配列 $movable_holiday に用意しておく。今後、ハッピーマンデー法が変更になった場合は、この配列を変更するだけで対応できるようになっている。
解説:振替休日
2112: /**
2113: * 指定した年月日が振替休日かどうかを求める.
2114: * 振替休日ならTRUEを返す.
2115: * @param int $year 西暦年
2116: * @param int $month 月
2117: * @param int $day 日
2118: * @return bool TRUE/FALSE
2119: */
2120: function isTransferHoliday($year, $month, $day) {
2121: $jd = $this->Gregorian2JD($year, $month, $day, 0, 0, 0);
2122: $j0 = $this->Gregorian2JD(1973, 4, 12, 0, 0, 0);
2123: if ($jd < $j0) return FALSE; //有効なのは1973年4月12日以降
2124:
2125: //当日が祝日なら FALSE
2126: if ($this->isFixedMovableHoliday($year, $month, $day)) return FALSE;
2127:
2128: $n = ($year <= 2006) ? 1 : 7; //改正法なら最大7日間遡る
2129: $jd--; //1日前
2130: for ($i = 0; $i < $n; $i++) { //無限ループに陥らないように
2131: list($yy, $mm, $dd) = $this->JD2Gregorian($jd);
2132: //祝日かつ日曜日なら振替休日
2133: if ($this->isFixedMovableHoliday($yy, $mm, $dd)
2134: && ($this->getWeekNumber($yy, $mm, $dd) == 0)) return TRUE;
2135: //祝日でなければ打ち切り
2136: if (! $this->isFixedMovableHoliday($yy, $mm, $dd)) break;
2137: $jd--; //1日前
2138: }
2139: return FALSE;
2140: }
ところがハッピーマンデー法が制定されてから以降は、日曜日、月曜日が連続して祝日になるケースが発生する。そこで、2007年(平成19年)1月以降は、
祝日が日曜にあたるときは、その日後において、その日に最も近い「国民の祝日」でない日を休日とすることになった。前述の場合は火曜日が祝日になる。
とくに2009年(平成21年)は、5月3日の日曜日が憲法記念日、月曜日のみどりの日、火曜日のこどもの日と、祝日が3日連続することになった。この場合は水曜日が振替休日となる。

ユーザー関数 isTransferHoliday は、与えられた西暦年月日が振替休日かどうか調べるものである。
前日が祝日である場合は、for ループを用い、日曜日まで祝日が続いているかどうか遡ってチェックするようにしている。連続していれば、その日は振替休日である。
ここで while ではなくforループを用いたのは、引数や他の祝日判定の異常で無限ループに陥ることがないようにするための配慮である。
解説:国民の休日
2142: /**
2143: * 指定した年月日が国民の休日かどうかを求める.
2144: * 国民の休日ならTRUEを返す.
2145: * @param int $year 西暦年
2146: * @param int $month 月
2147: * @param int $day 日
2148: * @return bool TRUE/FALSE
2149: */
2150: function isNationalHoliday($year, $month, $day) {
2151: if ($year < 2003) return FALSE; //有効なのは2003年以降
2152: $j0 = $this->Gregorian2JD($year, $month, $day, 0, 0, 0) - 1; //前日
2153: list($yy0, $mm0, $dd0) = $this->JD2Gregorian($j0);
2154: $j1 = $this->Gregorian2JD($year, $month, $day, 0, 0, 0) + 1; //翌日
2155: list($yy1, $mm1, $dd1) = $this->JD2Gregorian($j1);
2156:
2157: //前日と翌日が固定祝日または移動祝日なら国民の休日
2158: if ($this->isFixedMovableHoliday($yy0, $mm0, $dd0)
2159: && $this->isFixedMovableHoliday($yy1, $mm1, $dd1)) return TRUE;
2160: return FALSE;
2161: }

ユーザー関数 isTransferHoliday は、与えられた西暦年月日が国民の休日かどうかを調べる。
その翌日と前日が、固定祝日、移動祝日1、移動祝日2のいずれかでないかどうかを調べているだけである。
解説:祝日を求める
2163: /**
2164: * 指定した年月日が祝日であれば,その名称を求める.
2165: * 祝日でなければFALSEを返す.
2166: * @param int $year 西暦年
2167: * @param int $month 月
2168: * @param int $day 日
2169: * @return string 祝日の名称/FALSE=祝日ではない
2170: */
2171: function getHoliday($year, $month, $day) {
2172: //固定祝日
2173: $name = $this->getFixedHoliday($year, $month, $day, 'jp');
2174: if ($name != FALSE) return $name;
2175: //移動祝日(春分/秋分の日)
2176: $name = $this->getMovableHoliday1($year, $month, $day, 'jp');
2177: if ($name != FALSE) return $name;
2178: //移動祝日(ハッピーマンデー)
2179: $name = $this->getMovableHoliday2($year, $month, $day, 'jp');
2180: if ($name != FALSE) return $name;
2181: //振替休日
2182: if ($this->isTransferHoliday($year, $month, $day)) {
2183: return preg_match('/jp/i', $this->language) == 1 ? '振替休日' : 'holiday in lieu';
2184: }
2185: //国民の祝日
2186: if ($this->isNationalHoliday($year, $month, $day)) {
2187: return preg_match('/jp/i', $this->language) == 1 ? '国民の休日' : "Citizen's Holiday";
2188: }
2189: //祝日ではない
2190: return FALSE;
2191: }
2193: /**
2194: * 指定した年月日が祝日かどうかを求める.
2195: * 祝日ならTRUEを返す.
2196: * @param int $year 西暦年
2197: * @param int $month 月
2198: * @param int $day 日
2199: * @return bool TRUE/FALSE
2200: */
2201: function isHoliday($year, $month, $day) {
2202: return getHoliday($year, $month, $day, 'jp') == FALSE ? FALSE : TRUE;
2203: }
固定祝日、移動祝日1、移動祝日2、振替休日、国民の休日を順々に調べている。

ユーザー関数 isHoliday は、与えられた西暦年月日が祝日かどうかを調べるものである。

以上の関数を利用し、入力された西暦年から以降3年分の祝日一覧を表示するのがサンプル・プログラムである。
祝日と祭日
戦後、GHQの占領下において、神道に基づく儀礼は一切廃止されたため、「祭日」は無くなった。そして、国民が祝うべき「祝日」に切り替わったのである。
ところが実際は、新憲法が制定された1947年(昭和22年)を過ぎても戦前の祝日法が有効であり、ようやく1948年(昭和23年)になって新しい「国民の祝日に関する法律」(祝日法)が定められた。

「『国民の祝日』の由来がわかる小事典」(所功/PHP研究所/2003年(平成15年)08月)は、祝日を
- 祭日に基づく祝日
- 国家にちなむ祝日
- 人生に伴う祝日
参考書籍
![]() |
理科年表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で閏年かどうか判定する:ぱふぅ家のホームページ
- 秋分の日と敬老の日の微妙な関係:ぱふぅ家のホームページ
- 暦要項:国立天文台
- 国民の祝日について:内閣府
- 現在の祝日の一覧:こよみのページ
- 日本の祝日の変遷:こよみのページ
あらかじめ断っておくが、計算によって祝日を求めることは難しい。
「秋分の日と敬老の日の微妙な関係」で述べたように、法律によって祝日が変わるなどのルールがあるため、ある年の祝日を計算で完全に求めることはできない。
過去の祝日であれば、実際のカレンダーから祝日を抜き出してテーブルに用意しておき、それを引いた方が確実である。また、未来の祝日についても、アプリケーションやインターネットにあるものをテーブルとして取り込み、それを引いた方が手っ取り早く確実である。
ここでは、アプリケーションやインターネットにないような未来の祝日を求めることを目的に、あえて計算で導出することを考えてみることにする。
(2021年4月24日)PHP8対応,リファラ・チェック改良
(2020年11月30日)2021年の祝日変更に対応した。暦計算クラス pahooCalendar を差し替えることで、他のカレンダー関係のプログラムも祝日変更できる。
(2020年1月2日)暦計算クラス pahooCalendar を使用し、2019~2020年の祝日変更に対応した。