オレオレ・フレームワークに組み込んでいるクラスなんで、ガチガチの密結合です。多少環境に合わせて書き換え必要です。すんません…
よくよく見直してみると、Datetime() 使っていながら、所々 timestamp 使っているなあ…、気持ち悪いからそのうち修正しておきます修正しました。
<?php
namespace common\Date;
/**
* Holiday
*/
class Holiday
{
/**
* 月を表す英語表記
* @var array
*/
static protected $_arrMonth = array(
0 => ''
, 1 => 'January'
, 2 => 'February'
, 3 => 'March'
, 4 => 'April'
, 5 => 'May'
, 6 => 'June'
, 7 => 'July'
, 8 => 'August'
, 9 => 'September'
, 10 => 'October'
, 11 => 'November'
, 12 => 'December'
);
/**
* 曜日配列
* @var array
*/
static protected $_arrWeek = array(
0 => 'Sunday'
, 1 => 'Monday'
, 2 => 'Tuesday'
, 3 => 'Wednesday'
, 4 => 'Thursday'
, 5 => 'Friday'
, 6 => 'Saturday'
);
/**
* 休日配列
* @var array
*/
static protected $_holidayDefinition = array(
array('title' => '元日', 'start' => 1948, 'end' => null, 'month' => 1, 'day' => 1, 'weekNum' => null, 'week' => null)
, array('title' => '成人の日', 'start' => 1949, 'end' => 1999, 'month' => 1, 'day' => 15, 'weekNum' => null, 'week' => null)
, array('title' => '成人の日', 'start' => 2000, 'end' => null, 'month' => 1, 'day' => null, 'weekNum' => 2, 'week' => \Constants\Common::T_MONDAY)
, array('title' => '建国記念の日', 'start' => 1967, 'end' => null, 'month' => 2, 'day' => 11, 'weekNum' => null, 'week' => null)
, array('title' => '春分の日', 'start' => 1948, 'end' => null, 'month' => 3, 'day' => null, 'weekNum' => null, 'week' => null)
, array('title' => '天皇誕生日', 'start' => 1948, 'end' => 1988, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
, array('title' => 'みどりの日', 'start' => 1989, 'end' => 2006, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
, array('title' => '昭和の日', 'start' => 2007, 'end' => null, 'month' => 4, 'day' => 29, 'weekNum' => null, 'week' => null)
, array('title' => '憲法記念日', 'start' => 1948, 'end' => null, 'month' => 5, 'day' => 3, 'weekNum' => null, 'week' => null)
, array('title' => 'みどりの日', 'start' => 2007, 'end' => null, 'month' => 5, 'day' => 4, 'weekNum' => null, 'week' => null)
, array('title' => 'こどもの日', 'start' => 1948, 'end' => null, 'month' => 5, 'day' => 5, 'weekNum' => null, 'week' => null)
, array('title' => '海の日', 'start' => 1996, 'end' => 2002, 'month' => 7, 'day' => 20, 'weekNum' => null, 'week' => null)
, array('title' => '海の日', 'start' => 2003, 'end' => null, 'month' => 7, 'day' => null, 'weekNum' => 3, 'week' => \Constants\Common::T_MONDAY)
, array('title' => '山の日', 'start' => 2016, 'end' => null, 'month' => 8, 'day' => 11, 'weekNum' => null, 'week' => null)
, array('title' => '敬老の日', 'start' => 1956, 'end' => 2002, 'month' => 9, 'day' => 15, 'weekNum' => null, 'week' => null)
, array('title' => '敬老の日', 'start' => 2003, 'end' => null, 'month' => 9, 'day' => null, 'weekNum' => 3, 'week' => \Constants\Common::T_MONDAY)
, array('title' => '秋分の日', 'start' => 2003, 'end' => null, 'month' => 9, 'day' => null, 'weekNum' => null, 'week' => null)
, array('title' => '体育の日', 'start' => 1966, 'end' => 1999, 'month' => 10, 'day' => 10, 'weekNum' => null, 'week' => null)
, array('title' => '体育の日', 'start' => 2000, 'end' => null, 'month' => 10, 'day' => null, 'weekNum' => 2, 'week' => \Constants\Common::T_MONDAY)
, array('title' => '文化の日', 'start' => 1948, 'end' => null, 'month' => 11, 'day' => 3, 'weekNum' => null, 'week' => null)
, array('title' => '勤労感謝の日', 'start' => 1948, 'end' => null, 'month' => 11, 'day' => 23, 'weekNum' => null, 'week' => null)
, array('title' => '天皇誕生日', 'start' => 1989, 'end' => null, 'month' => 12, 'day' => 23, 'weekNum' => null, 'week' => null)
);
/**
* 曜日から日付を取得する
* @param integer $y
* @param integer $m
* @param integer $n
* @param integer $w
* @return string
*/
static protected function getDateFromWeek($y, $m, $n, $w)
{
$time = sprintf("%04d-%02d-%02d", $y, $m, 1);
$objDate = new \DateTime($time);
// 指定曜日の最初の日付を取得して指定週の日付を算出
$first_weekday = $objDate->format('w');
$result_day = $w - $first_weekday + 1;
if ($result_day < 1) {
$result_day += 7;
}
$result_day = $result_day + ($n - 1) * 7;
if ($result_day > 31) {
return 0;
}
return sprintf("%04d-%02d-%02d", $y, $m, $result_day);
}
/**
* 年から休日の配列を取得する
* @param integer $intYear
* @return array
* @throws \common\InvalidErrorException
*/
static public function get($intYear)
{
if (1851 > $intYear || 2099 < $intYear) {
$msg = '[year]パラメータが不正です。';
throw new \common\InvalidErrorException($msg);
}
$res = array();
$alt = null;
$arrHoliday = self::$_holidayDefinition;
foreach ($arrHoliday as $i => $holiday) {
if ($holiday['start'] <= $intYear &&
($intYear <= $holiday['end'] || null == $holiday['end'])
) {
if (!is_null($holiday['day'])) {
$res[] = array(
'title' => $holiday['title']
, 'year' => (int) $intYear
, 'month' => $holiday['month']
, 'day' => $holiday['day']
, 'date' => sprintf("%04d-%02d-%02d"
, $intYear
, $holiday['month']
, $holiday['day']
)
);
} else if (!is_null($holiday['weekNum']) &&
!is_null($holiday['week'])) {
// 第○週×曜日
$intMonth = $holiday['month'];
$weekNum = $holiday['weekNum'];
$week = $holiday['week'];
$timestamp = self::getDateFromWeek(
$intYear
, $intMonth
, $weekNum
, $week
);
$objDate = new \DateTime($timestamp);
$res[] = array(
'title' => $holiday['title']
, 'year' => (int) $objDate->format('Y')
, 'month' => (int) $objDate->format('m')
, 'day' => (int) $objDate->format('d')
, 'date' => $timestamp
);
} else if (3 == $holiday['month']) {
// 春分の日
$res[] = array(
'title' => $holiday['title']
, 'year' => (int) $intYear
, 'month' => (int) $holiday['month']
, 'day' => (int) self::springHoliday($intYear)
, 'date' => sprintf("%04d-%02d-%02d"
, $intYear
, $holiday['month']
, self::springHoliday($intYear)
)
);
} else if (9 == $holiday['month']) {
// 秋分の日
$res[] = array(
'title' => $holiday['title']
, 'year' => (int) $intYear
, 'month' => (int) $holiday['month']
, 'day' => (int) self::autumnHoliday($intYear)
, 'date' => sprintf("%04d-%02d-%02d"
, $intYear
, $holiday['month']
, self::autumnHoliday($intYear)
)
);
}
}
}
$resHoliday = array();
foreach ($res as $i => $holiday) {
$resHoliday[] = $holiday;
// 振替休日
$alt = self::alternativeHoliday(
$intYear
, $holiday['month']
, $holiday['day']
);
if (isset($alt) && !is_null($alt) && isset($res[$i + 1])) {
$nextHolidy = $res[$i + 1];
if ($nextHolidy['month'] != $alt['month'] ||
$nextHolidy['day'] != $alt['day']) {
$resHoliday[] = $alt;
}
}
// 国民の休日
$objHoliday = new \DateTime;
$objHoliday->setDate(
$holiday['year']
, $holiday['month']
, $holiday['day']
);
$objTomorrow = $objHoliday->add(new \DateInterval('P1D'));
$objDayaftertomorrow = $objHoliday->add(new \DateInterval('P1D'));
if (isset($res[$i + 1])) {
$nextHolidy = $res[$i + 1];
if ((int) $nextHolidy['month'] == (int) $objDayaftertomorrow->format('m') &&
(int) $nextHolidy['day'] == (int) $objDayaftertomorrow->format('d')) {
$resHoliday[] = array(
'title' => '国民の休日'
, 'year' => (int) $intYear
, 'month' => (int) $objTomorrow->format('m')
, 'day' => (int) $objTomorrow->format('d')
, 'date' => sprintf(
"%04d-%02d-%02d"
, $intYear
, (int) $objTomorrow->format('m')
, (int) $objTomorrow->format('d')
)
);
}
}
}
return $resHoliday;
}
/**
* 振替休日
* @param integer $intYear
* @param integer $intMonth
* @param integer $intDay
* @return array
*/
static protected function alternativeHoliday($intYear, $intMonth, $intDay)
{
$objDate = new \DateTime(
sprintf("%04d-%02d-%02d", $intYear, $intMonth, $intDay)
);
if (0 == $objDate->format('w')) {
$objDate->add(new \DateInterval('P1D'));
return array(
'title' => '振替休日'
, 'year' => (int) $intYear
, 'month' => (int) $objDate->format('m')
, 'day' => (int) $objDate->format('d')
, 'date' => $objDate->format('Y-m-d')
);
} else {
return null;
}
}
/**
* 春分の日
* @param integer $intYear
* @return string
*/
static protected function springHoliday($intYear)
{
if (1851 <= $intYear && 1899 >= $intYear) {
$day = 19.8277 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
} else if (1900 <= $intYear && 1979 >= $intYear) {
$day = 20.8357 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
} else if (1980 <= $intYear && 2099 >= $intYear) {
$day = 20.8431 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
} else if (2100 <= $intYear && 2150 >= $intYear) {
$day = 21.8510 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
}
return floor($day);
}
/**
* 秋分の日
* @param integer $intYear
* @return string
*/
static protected function autumnHoliday($intYear)
{
if (1851 <= $intYear && 1899 >= $intYear) {
$day = 22.2588 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
} else if (1900 <= $intYear && 1979 >= $intYear) {
$day = 23.2588 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1983) / 4);
} else if (1980 <= $intYear && 2099 >= $intYear) {
$day = 23.2488 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
} else if (2100 <= $intYear && 2150 >= $intYear) {
$day = 24.2488 + 0.242194 * ($intYear - 1980) - floor(($intYear - 1980) / 4);
}
return floor($day);
}
}