PHP 祝日取得クラス
日本の祝日を返すクラスです。
以前より個人的に使っていた処理がクラス化していなかった上、祝日定義の記述自体にも多重に三項演算子を多用していて少々メンテナンスしにくかったので、クラス化のついでにその辺も作り直しました。
春分の日及び秋分の日については簡易的な実装ですので、現在から遠い年では正しい値を返す保証はありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
<?php class Holiday { private $holidayDefinitions; private $year; private $month; private $result; private $useIndefiniteHoliday; private $resultType; private $dateTime; public function __construct($year = 0) { // 祝日定義 // ('国民の祝日に関する法律'が公布・施行された1948年7月20日以降のもののみ) $this->holidayDefinitions = [ 1 => [ '1949:1' => '元日', '1949:15, 2000:2_1' => '成人の日', ], 2 => [ '1967:11' => '建国記念の日', '2020:23' => '天皇誕生日', '1989:24, 1990:0' => '大喪の礼', ], 3 => [ '1949:s' => '春分の日', ], 4 => [ '1959:10, 1960:0' => '結婚の儀', '1949:29' => '天皇誕生日, 1989:みどりの日, 2007:昭和の日', ], 5 => [ '2019:1, 2020:0' => '皇太子殿下即位・改元', '1949:3' => '憲法記念日', '2007:4' => 'みどりの日', '1949:5' => 'こどもの日', ], 6 => [ '1993:9, 1994:0' => '結婚の儀', ], 7 => [ '1996:20, 2003:3_1, 2020:23, 2021:22, 2022:3_1' => '海の日', '2020:24, 2021:23, 2022:0' => 'スポーツの日', ], 8 => [ '2016:11, 2020:10, 2021:8, 2022:11' => '山の日', ], 9 => [ '1966:15, 2003:3_1' => '敬老の日', '1948:a' => '秋分の日', ], 10 => [ '1966:10, 2000:2_1, 2020:0, 2022:2_1' => '体育の日, 2020:スポーツの日', '2019:22, 2020:0' => '即位礼正殿の儀', ], 11 => [ '1948:3' => '文化の日', '1990:12, 1991:0' => '即位礼正殿の儀', '1948:23' => '勤労感謝の日', ], 12 => [ '1989:23, 2019:0' => '天皇誕生日', ], ]; $this->dateTime = new DateTime(); $this->dateTime->setTime(0, 0, 0); if($year < 1) $year = $this->dateTime->format('Y'); $this->year = (int) $year; $this->month = (int) $this->dateTime->format('m'); $this->result = []; $this->useIndefiniteHoliday = 1; $this->resultType = 0; } /** * 1年分のリストを返す */ public function getHolidayOfYear($year = 0) { if($year < 1) $year = $this->year; $year = (int) $year; if(!isset($this->result[$year])) { // 該当年の祝日配列に変換 $holiday = []; $equinox = .242194 * ($year - 1980) - floor(($year - 1980) / 4); foreach($this->holidayDefinitions as $month => $currentMonthData) { $holiday[$month] = []; foreach($currentMonthData as $days => $names) { // 対象年・日取得 $days = explode(',', $days); $arrTmp = []; foreach($days as $tmp) { $tmp = explode(':', $tmp); $arrTmp[(int) $tmp[0]] = trim($tmp[1]); } $yearTmp = 0; foreach(array_keys($arrTmp) as $tmp) if($year >= $tmp && $tmp >= $yearTmp) $yearTmp = $tmp; if($yearTmp == 0) continue; // 日を記述形式ごとに取得 if($arrTmp[$yearTmp] === 's') $day = floor(20.8431 + $equinox); elseif($arrTmp[$yearTmp] === 'a') $day = floor(23.2488 + $equinox); elseif(strpos($arrTmp[$yearTmp], '_') !== false) { [$num, $w] = explode('_', $arrTmp[$yearTmp]); $day = $this->getDayOfNumWeek($year, $month, $num, $w); } else $day = $arrTmp[$yearTmp]; if($day < 1) continue; // 名称取得 $names = explode(',', $names); $arrTmp = []; foreach($names as $tmp) { $tmp = explode(':', $tmp); if(count($tmp) == 1) $arrTmp[0] = trim($tmp[0]); else $arrTmp[(int) $tmp[0]] = trim($tmp[1]); } $yearTmp = 0; foreach(array_keys($arrTmp) as $tmp) if($year >= $tmp && $tmp >= $yearTmp) $yearTmp = $tmp; $holiday[$month][$day] = !isset($holiday[$month][$day]) ? $arrTmp[$yearTmp] : $holiday[$month][$day]. ', '. $arrTmp[$yearTmp]; } } // 国民の休日・振替休日 if($this->useIndefiniteHoliday) $holiday = $this->indefiniteHoliday($holiday, $year); foreach($holiday as $k => $v) ksort($holiday[$k]); $this->result[$year] = $holiday; } return $this->resultType ? $this->convertLinear($year, $this->result[$year]) : $this->result[$year]; } /** * 国民の休日・振替休日 */ private function indefiniteHoliday($holiday, $year) { for($month = 1; $month <= 12; $month++) { // 月末日 $lastDay = (int) $this->dateTime->setDate($year, $month, 1)->format('t'); for($day = 1; $day <= $lastDay; $day++) { // 前日の月日 $this->dateTime->setDate($year, $month, $day)->modify('-1 day'); $prevMonth = (int) $this->dateTime->format('m'); $prevDay = (int) $this->dateTime->format('d'); // 祝日に挟まれた平日を国民の休日に変更(1986年以降) if( $year >= 1986 && isset($holiday[$prevMonth][$prevDay]) ) { // 翌日の月日 $this->dateTime->setDate($year, $month, $day)->modify('+1 day'); $nextMonth = (int) $this->dateTime->format('m'); $nextDay = (int) $this->dateTime->format('d'); $this->dateTime->setDate($year, $month, $day); if( isset($holiday[$nextMonth][$nextDay]) && !isset($holiday[$month][$day]) && (int) $this->dateTime->format('w') !== 0 ) { $holiday[$month][$day] = '国民の休日'; } } $this->dateTime->setDate($year, $month, $day); // 振替休日(1973年4月以降) if(($year == 1973 && $month >= 4 || $year > 1973) && // 祝日かつ日曜 isset($holiday[$month][$day]) && (int) $this->dateTime->format('w') === 0 ) { // その日以降の直近の平日を振替休日に for($i = 1; $i < 7; $i++) { $this->dateTime->setDate($year, $month, $day)->modify("+$i day"); $m = (int) $this->dateTime->format('m'); $d = (int) $this->dateTime->format('d'); if(!isset($holiday[$m][$d])) { $holiday[$m][$d] = '振替休日'; break; } } } } } return $holiday; } /** * $year年 $month月 第$num $w曜日に該当する日を返す */ private function getDayOfNumWeek($year, $month, $num, $w) { $firstDayWeek = (int) $this->dateTime->setDate($year, $month, 1)->format('w'); return 1 + ($num - 1) * 7 + (7 + $w - $firstDayWeek) % 7; } /** * YYYY-MM-DDをキーとした連想配列に変換 */ private function convertLinear($year, $array) { $arrTmp = []; foreach($array as $month => $currentMonthData) { foreach($currentMonthData as $days => $names) { $arrTmp[sprintf('%04d-%02d-%02d', $year, $month, $days)] = $names; } } return $arrTmp; } /** * 1か月分のリストを返す */ public function getHolidayOfMonth($month = 0) { if($month < 1 || $month > 12) $month = $this->month; $year = $this->year; // 該当年の結果が未取得であれば取得 if(!isset($this->result[$year])) $this->getHolidayOfYear(); if($this->resultType) { $arrTmp = []; foreach($this->result[$year][(int) $month] as $days => $names) { $arrTmp[sprintf('%04d-%02d-%02d', $year, $month, $days)] = $names; } return $arrTmp; } else { return $this->result[$year][(int) $month]; } } /** * 国民の休日・振替休日 使用フラグ変更 */ public function setUseIndefiniteHoliday($flg = 1) { $this->useIndefiniteHoliday = $flg == 1 ? 1 : 0; // 取得済みの結果をリセット $this->result = []; } /** * 戻り値形式変更 */ public function setResultType($flg = 0) { $this->resultType = $flg == 0 ? 0 : 1; } /** * 年変更 */ public function setYear($year = 0) { if($year < 1) $year = (new DateTime())->format('Y'); $this->year = (int) $year; } } |
インスタンス生成
new Holiday([$year])
year
年プロパティの初期値。省略、または0以下の値を渡した場合は現在の年で設定。
1 2 3 |
$holiday = new Holiday(2020); $holiday = new Holiday(); $holiday = new Holiday; |
メソッド
年プロパティ変更
setYear([$year])
year
年。省略、または0以下の値を渡した場合は現在の年で設定。
1 2 3 |
$holiday = new Holiday; $holiday->setYear(2000); $holiday->setYear(); |
1年分の祝日リストを取得
getHolidayOfYear([$year])
year
年。省略、または0以下の値を渡した場合は年プロパティの値を使用。
インスタンス内の年プロパティ変更はしません。
1 2 |
$holiday = new Holiday; print_r($holiday->getHolidayOfYear()); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
Array ( [1] => Array ( [1] => 元日 [13] => 成人の日 ) [2] => Array ( [11] => 建国記念の日 [23] => 天皇誕生日 [24] => 振替休日 ) [3] => Array ( [20] => 春分の日 ) [4] => Array ( [29] => 昭和の日 ) [5] => Array ( [3] => 憲法記念日 [4] => みどりの日 [5] => こどもの日 [6] => 振替休日 ) [6] => Array ( ) [7] => Array ( [23] => 海の日 [24] => スポーツの日 ) [8] => Array ( [10] => 山の日 ) [9] => Array ( [21] => 敬老の日 [22] => 秋分の日 ) [10] => Array ( ) [11] => Array ( [3] => 文化の日 [23] => 勤労感謝の日 ) [12] => Array ( ) ) |
1か月分の祝日リストを取得
getHolidayOfMonth([$month])
month
月。省略時または範囲外の値を指定した場合は現在の月が使用されます。
年はインスタンス内の年プロパティを使用します。
1 2 |
$holiday = new Holiday; print_r($holiday->getHolidayOfMonth()); |
1 2 3 4 5 |
Array ( [23] => 海の日 [24] => スポーツの日 ) |
戻り値のリスト形式変更
setResultType([$resultType])
resultType
戻り値の形式
0: 月、日をキーとした連想配列(デフォルト)
1: YYYY-MM-DD をキーとした連想配列
1 2 3 4 |
$holiday = new Holiday; $holiday->setResultType(1); print_r($holiday->getHolidayOfYear()); print_r($holiday->getHolidayOfMonth(5)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Array ( [2020-01-01] => 元日 [2020-01-13] => 成人の日 [2020-02-11] => 建国記念の日 [2020-02-23] => 天皇誕生日 [2020-02-24] => 振替休日 [2020-03-20] => 春分の日 [2020-04-29] => 昭和の日 [2020-05-03] => 憲法記念日 [2020-05-04] => みどりの日 [2020-05-05] => こどもの日 [2020-05-06] => 振替休日 [2020-07-23] => 海の日 [2020-07-24] => スポーツの日 [2020-08-10] => 山の日 [2020-09-21] => 敬老の日 [2020-09-22] => 秋分の日 [2020-11-03] => 文化の日 [2020-11-23] => 勤労感謝の日 ) Array ( [2020-05-03] => 憲法記念日 [2020-05-04] => みどりの日 [2020-05-05] => こどもの日 [2020-05-06] => 振替休日 ) |
国民の休日及び振替休日の使用指定
setUseIndefiniteHoliday([$useIndefiniteHoliday])
useIndefiniteHoliday
0: 使用しない
1: 使用する(デフォルト)
1 2 3 4 5 |
$holiday = new Holiday(2019); $holiday->setResultType(1); print_r($holiday->getHolidayOfMonth(5)); $holiday->setUseIndefiniteHoliday(0); print_r($holiday->getHolidayOfMonth(5)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Array ( [2019-05-01] => 皇太子殿下即位・改元 [2019-05-02] => 国民の休日 [2019-05-03] => 憲法記念日 [2019-05-04] => みどりの日 [2019-05-05] => こどもの日 [2019-05-06] => 振替休日 ) Array ( [2019-05-01] => 皇太子殿下即位・改元 [2019-05-03] => 憲法記念日 [2019-05-04] => みどりの日 [2019-05-05] => こどもの日 ) |