祝日・休日算出クラス

オレオレ・フレームワークに組み込んでいるクラスなんで、ガチガチの密結合です。多少環境に合わせて書き換え必要です。すんません…

よくよく見直してみると、Datetime() 使っていながら、所々 timestamp 使っているなあ…、気持ち悪いからそのうち~~修正しておきます~~修正しました。

```PHP
<?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);
	}

}
```