Last active
June 17, 2019 02:18
-
-
Save chiyoyo/0a653f85dd468364d086 to your computer and use it in GitHub Desktop.
祝日を自動判定するDateTime拡張クラス ref: https://qiita.com/chiyoyo/items/539dc2840a1b70a8e2c3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* 祝日かどうか判定できるDateTime拡張クラス | |
* usage: $holidayDateTime->holiday(); | |
*/ | |
class HolidayDateTime extends DateTime | |
{ | |
/** 祝日一覧 */ | |
// 種別: | |
// fixed=日付固定 | |
// happy=指定の週の月曜日 | |
// spring=春分の日専用 | |
// autumn=秋分の日専用 | |
private static $holidays = [ | |
// 種別, 月, 日or週, 開始年, 終了年, 祝日名 | |
['fixed', 1, 1, 1949, 9999, '元日'], | |
['fixed', 1, 15, 1949, 1999, '成人の日'], | |
['happy', 1, 2, 2000, 9999, '成人の日'], | |
['fixed', 2, 11, 1967, 9999, '建国記念の日'], | |
['fixed', 2, 23, 2020, 9999, '天皇誕生日'], | |
['spring', 3, 0, 1949, 9999, '春分の日'], | |
['fixed', 4, 29, 1949, 1989, '天皇誕生日'], | |
['fixed', 4, 29, 1990, 2006, 'みどりの日'], | |
['fixed', 4, 29, 2007, 9999, '昭和の日'], | |
['fixed', 5, 3, 1949, 9999, '憲法記念日'], | |
['fixed', 5, 4, 1988, 2006, '国民の休日'], | |
['fixed', 5, 4, 2007, 9999, 'みどりの日'], | |
['fixed', 5, 5, 1949, 9999, 'こどもの日'], | |
['happy', 7, 3, 2021, 9999, '海の日'], | |
['fixed', 7, 23, 2020, 2020, '海の日'], | |
['happy', 7, 3, 2003, 2019, '海の日'], | |
['fixed', 7, 20, 1996, 2002, '海の日'], | |
['fixed', 8, 11, 2021, 9999, '山の日'], | |
['fixed', 8, 10, 2020, 2020, '山の日'], | |
['fixed', 8, 11, 2016, 2019, '山の日'], | |
['autumn', 9, 0, 1948, 9999, '秋分の日'], | |
['fixed', 9, 15, 1966, 2002, '敬老の日'], | |
['happy', 9, 3, 2003, 9999, '敬老の日'], | |
['fixed', 10, 10, 1966, 1999, '体育の日'], | |
['happy', 10, 2, 2000, 2019, '体育の日'], | |
['fixed', 7, 24, 2020, 2020, 'スポーツの日'], | |
['happy', 10, 2, 2021, 9999, 'スポーツの日'], | |
['fixed', 11, 3, 1948, 9999, '文化の日'], | |
['fixed', 11, 23, 1948, 9999, '勤労感謝の日'], | |
['fixed', 12, 23, 1989, 2018, '天皇誕生日'], | |
//以下、1年だけの祝日 | |
['fixed', 4, 10, 1959, 1959, '皇太子明仁親王の結婚の儀'], | |
['fixed', 2, 24, 1989, 1989, '昭和天皇の大喪の礼'], | |
['fixed', 11, 12, 1990, 1990, '即位礼正殿の儀'], | |
['fixed', 6, 9, 1993, 1993, '皇太子徳仁親王の結婚の儀'], | |
['fixed', 5, 1, 2019, 2019, '天皇の即位の日'], | |
['fixed', 10, 22, 2019, 2019, '即位礼正殿の儀'], | |
]; | |
/** | |
* 祝日を取得 | |
*/ | |
public function holiday() | |
{ | |
// 設定された休日チェック | |
$result = $this->checkHoliday(); | |
if ($result !== false) return $result; | |
// 振替休日チェック | |
$result = $this->checkTransferHoliday(); | |
if ($result !== false) return $result; | |
// 国民の休日チェック | |
$result = $this->checkNationalHoliday(); | |
return $result; | |
} | |
/** | |
* 設定された休日のみチェック | |
* 国民の休日と振替休日はチェックしない | |
*/ | |
public function checkHoliday() | |
{ | |
$result = false; | |
// 全ての祝日を判定 | |
foreach(self::$holidays as $holiday) { | |
list($method, $month, $day, $start, $end, $name) = $holiday; | |
$method .= 'Holiday'; | |
$result = $this->$method($month, $day, $start, $end, $name); | |
if ($result) { | |
return $result; | |
} | |
} | |
return $result; | |
} | |
/** | |
* 振替休日チェック | |
*/ | |
public function checkTransferHoliday() | |
{ | |
// 施行日チェック | |
$d = new DateTime('1973-04-12'); | |
if ($this < $d) return false; | |
// 当日が祝日の場合はfalse | |
if ($this->checkHoliday()) return false; | |
$num = ($this->year <= 2006) ? 1 : 7; //改正法なら最大7日間遡る | |
$d = clone $this; | |
$d->modify('-1 day'); | |
$isTransfer = false; | |
for ($i = 0 ; $i < $num ; $i++) { | |
if ($d->checkHoliday()) { | |
// 祝日かつ日曜ならば振替休日 | |
if ($d->dayOfWeek == 0) { | |
$isTransfer = true; | |
break; | |
} | |
$d->modify('-1 day'); | |
} else { | |
break; | |
} | |
} | |
return $isTransfer ? '振替休日' : false; | |
} | |
/** | |
* 国民の休日かどうかチェック | |
*/ | |
public function checkNationalHoliday() | |
{ | |
// 施行日チェック | |
$d = new DateTime('2003-01-01'); | |
if ($this < $d) return false; | |
$before = clone $this; | |
$before->modify('-1 day'); | |
if ($before->checkHoliday() === false) return false; | |
$after = clone $this; | |
$after->modify('+1 day'); | |
if ($after->checkHoliday() === false) return false; | |
return '国民の休日'; | |
} | |
/** | |
* 固定祝日かどうか | |
*/ | |
private function fixedHoliday($month, $day, $start, $end, $name) | |
{ | |
if ($this->isWithinYear($start, $end) === false) return false; | |
if ($this->month != $month) return false; | |
if ($this->day != $day) return false; | |
return $name; | |
} | |
/** | |
* ハッピーマンデー | |
*/ | |
private function happyHoliday($month, $week, $start, $end, $name) | |
{ | |
if ($this->isWithinYear($start, $end) === false) return false; | |
if ($this->month != $month) return false; | |
// 第*月曜日の日付を求める | |
$w = 1; // 月曜日固定 | |
$d1 = new HolidayDateTime($this->format('Y-m-1')); | |
$w1 = intval($d1->dayOfWeek); | |
$day = $w - $w1 < 0 ? 7 + $w - $w1 : $w - $w1; | |
$day++; | |
$day = $day + 7 * ($week - 1); | |
if ($this->day != $day) return false; | |
return $name; | |
} | |
/** | |
* 春分の日 | |
*/ | |
private function springHoliday($month, $dummy, $start, $end, $name) | |
{ | |
if ($this->isWithinYear($start, $end) === false) return false; | |
if ($this->month != $month) return false; | |
$year = $this->year; | |
$day = floor(20.8431 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4)); | |
if ($this->day != $day) return false; | |
return $name; | |
} | |
/** | |
* 秋分の日 | |
*/ | |
private function autumnHoliday($month, $dummy, $start, $end, $name) | |
{ | |
if ($this->isWithinYear($start, $end) === false) return false; | |
if ($this->month != $month) return false; | |
$year = $this->year; | |
$day = floor(23.2488 + 0.242194 * ($year - 1980) - floor(($year - 1980) / 4)); | |
if ($this->day != $day) return false; | |
return $name; | |
} | |
/** | |
* 年が祝日適用範囲内であるか | |
*/ | |
private function isWithinYear($start, $end) | |
{ | |
if ($this->year < $start || $end < $this->year) { | |
return false; | |
} | |
return true; | |
} | |
// 以下Carbonを継承している場合は削除すべし | |
public function __get($name) | |
{ | |
switch (true) { | |
case array_key_exists($name, $formats = [ | |
'year' => 'Y', | |
'month' => 'n', | |
'day' => 'j', | |
'hour' => 'G', | |
'minute' => 'i', | |
'second' => 's', | |
'micro' => 'u', | |
'dayOfWeek' => 'w', | |
'dayOfYear' => 'z', | |
'weekOfYear' => 'W', | |
'daysInMonth' => 't', | |
'timestamp' => 'U', | |
]): | |
return (int) $this->format($formats[$name]); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$datetime = new HolidayDateTime(); | |
$datetime->holiday(); | |
// 祝日の場合:"勤労感謝の日" | |
// 平日の場合:false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment