<?php

/*

※以下の祝日関連関数は
http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
および
http://www.nao.ac.jp/koyomi/topics/tex/topics1997/node1.html
(追記: ↑ってもうないじゃん…)
の記述を元に作成されています。

*/

function is_holiday($date, &$holiday_name, &$holiday_description) {

	if(is_numeric($date)) {
		$epoch = $date;
	} else {
		$epoch = strtotime($date);
	}
	$y = date('Y', $epoch);
	$m_d = date('m-d', $epoch);

	if($y < 2007) {

		switch($m_d) {
		case '01-01':
			$holiday_name = '元日';
			$holiday_description = '年のはじめを祝う。';
			return true;
		case '04-29':
			$holiday_name = 'みどりの日';
			$holiday_description = '自然に親しむとともにその恩恵に感謝し、豊かな心をはぐくむ。';
			return true;
		case '05-03':
			$holiday_name = '憲法記念日';
			$holiday_description = '日本国憲法の施行を記念し、国の成長を期する。';
			return true;
		case '05-05':
			$holiday_name = 'こどもの日';
			$holiday_description = 'こどもの人格を重んじ、こどもの幸福をはかるとともに、母に感謝する。';
			return true;
		case '11-03':
			$holiday_name = '文化の日';
			$holiday_description = '自由と平和を愛し、文化をすすめる。';
			return true;
		case '11-23':
			$holiday_name = '勤労感謝の日';
			$holiday_description = '勤労をたっとび、生産を祝い、国民たがいに感謝しあう。';
			return true;
		case '12-23':
			$holiday_name = '天皇誕生日';
			$holiday_description = '天皇の誕生日を祝う。';
			return true;
		case get_national_foundation_day():
			$holiday_name = '建国記念の日';
			$holiday_description = '政令で定める日	建国をしのび、国を愛する心を養う。';
			return true;
		}

	} else {

		switch($m_d) {
		case '01-01':
			$holiday_name = '元日';
			$holiday_description = '年のはじめを祝う。';
			return true;
		case '04-29':
			$holiday_name = '昭和の日';
			$holiday_description = '激動の日々を経て、復興を遂げた昭和の時代を顧み、国の将来に思いをいたす。';
			return true;
		case '05-03':
			$holiday_name = '憲法記念日';
			$holiday_description = '日本国憲法の施行を記念し、国の成長を期する。';
			return true;
		case '05-04':
			$holiday_name = 'みどりの日';
			$holiday_description = '自然に親しむとともにその恩恵に感謝し、豊かな心をはぐくむ。';
			return true;
		case '05-05':
			$holiday_name = 'こどもの日';
			$holiday_description = 'こどもの人格を重んじ、こどもの幸福をはかるとともに、母に感謝する。';
			return true;
		case '11-03':
			$holiday_name = '文化の日';
			$holiday_description = '自由と平和を愛し、文化をすすめる。';
			return true;
		case '11-23':
			$holiday_name = '勤労感謝の日';
			$holiday_description = '勤労をたっとび、生産を祝い、国民たがいに感謝しあう。';
			return true;
		case '12-23':
			$holiday_name = '天皇誕生日';
			$holiday_description = '天皇の誕生日を祝う。';
			return true;
		case get_national_foundation_day():
			$holiday_name = '建国記念の日';
			$holiday_description = '政令で定める日	建国をしのび、国を愛する心を養う。';
			return true;
		}

	}

	switch(date('n', $epoch).'-'.ceil(date('j', $epoch) / 7).'-'.date('w', $epoch)) {
	case '1-2-1':	// １月の第２月曜日
		$holiday_name = '成人の日';
		$holiday_description = 'おとなになったことを自覚し、みずから生き抜こうとする青年を祝いはげます。';
		return true;
	case '7-3-1':	// ７月の第３月曜日
		$holiday_name = '海の日';
		$holiday_description = '海の恩恵に感謝するとともに、海洋国日本の繁栄を願う。';
		return true;
	case '9-3-1':	// ９月の第３月曜日
		$holiday_name = '敬老の日';
		$holiday_description = '多年にわたり社会につくしてきた老人を敬愛し、長寿を祝う。';
		return true;
	case '10-2-1':	// １０月の第２月曜日
		$holiday_name = '体育の日';
		$holiday_description = 'スポーツにしたしみ、健康な心身をつちかう。';
		return true;
	}

	if(is_vernal_equinox_day($y, $m_d)) {
		$holiday_name = '春分の日';
		$holiday_description = '自然をたたえ、生物をいつくしむ。';
		return true;
	}
	if(is_autumnal_equinox_day($y, $m_d)) {
		$holiday_name = '秋分の日';
		$holiday_description = '祖先をうやまい、なくなった人々をしのぶ。';
		return true;
	}

	if(!is_numeric($date)) {

		$epoch_day_before = $epoch - 86400;
		if(is_holiday($epoch_day_before, $dummy, $dummy)) {	// 前日が祝日
	
			if(date('w', $epoch_day_before) == 0) {	// 前日が日曜で祝日
				$holiday_name = '振替休日';
				$holiday_description = null;
				return true;
			}
	
			if(is_holiday(($epoch + 86400), $dummy, $dummy)) {		// 前日も翌日も祝日
				$holiday_name = '国民の休日';
				$holiday_description = null;
				return true;
			}

			if($y >= 2007) {
				$epoch_day_before -= 86400;
				while(is_holiday($epoch_day_before, $dummy, $dummy)) {		// 前日以前が祝日の連続になっている場合
					if(date('w', $epoch_day_before) == 0) {	// 前日以前が祝日の連続で、日曜が重なる場合
						$holiday_name = '振替休日';
						$holiday_description = null;
						return true;
					}
					$epoch_day_before -= 86400;
				}
			}

		}

	}

	$holiday_name = null;
	$holiday_description = null;
	return false;

}

function get_national_foundation_day() {
	return '02-11';
}

function is_vernal_equinox_day($y, $m_d) {
	static $vernal_equinox_days;
	if(!isset($vernal_equinox_days)) {
		$vernal_equinox_days = array(
			1925 => '03-21',
			1926 => '03-21',
			1927 => '03-21',
			1928 => '03-21',
			1929 => '03-21',
			1930 => '03-21',
			1931 => '03-21',
			1932 => '03-21',
			1933 => '03-21',
			1934 => '03-21',
			1935 => '03-21',
			1936 => '03-21',
			1937 => '03-21',
			1938 => '03-21',
			1939 => '03-21',
			1940 => '03-21',
			1941 => '03-21',
			1942 => '03-21',
			1943 => '03-21',
			1944 => '03-21',
			1945 => '03-21',
			1946 => '03-21',
			1947 => '03-21',
			1948 => '03-21',
			1949 => '03-21',
			1950 => '03-21',
			1951 => '03-21',
			1952 => '03-21',
			1953 => '03-21',
			1954 => '03-21',
			1955 => '03-21',
			1956 => '03-21',
			1957 => '03-21',
			1958 => '03-21',
			1959 => '03-21',
			1960 => '03-20',
			1961 => '03-21',
			1962 => '03-21',
			1963 => '03-21',
			1964 => '03-20',
			1965 => '03-21',
			1966 => '03-21',
			1967 => '03-21',
			1968 => '03-20',
			1969 => '03-21',
			1970 => '03-21',
			1971 => '03-21',
			1972 => '03-20',
			1973 => '03-21',
			1974 => '03-21',
			1975 => '03-21',
			1976 => '03-20',
			1977 => '03-21',
			1978 => '03-21',
			1979 => '03-21',
			1980 => '03-20',
			1981 => '03-21',
			1982 => '03-21',
			1983 => '03-21',
			1984 => '03-20',
			1985 => '03-21',
			1986 => '03-21',
			1987 => '03-21',
			1988 => '03-20',
			1989 => '03-21',
			1990 => '03-21',
			1991 => '03-21',
			1992 => '03-20',
			1993 => '03-20',
			1994 => '03-21',
			1995 => '03-21',
			1996 => '03-20',
			1997 => '03-20',
			1998 => '03-21',
			1999 => '03-21',

			2000 => '03-20',
			2001 => '03-20',
			2002 => '03-21',
			2003 => '03-21',
			2004 => '03-20',
			2005 => '03-20',
			2006 => '03-21',
			2007 => '03-21',
			2008 => '03-20',
			2009 => '03-20',
			2010 => '03-21',
			2011 => '03-21',
			2012 => '03-20',
			2013 => '03-20',
			2014 => '03-21',
			2015 => '03-21',
		);
	}

//	return isset($vernal_equinox_days[$y]) ? ($vernal_equinox_days[$y] == $m_d) : null;
	return $m_d == (isset($vernal_equinox_days[$y]) ? $vernal_equinox_days[$y] : get_equinox_day_by_calc($y, 'vernal'));

}

function is_autumnal_equinox_day($y, $m_d) {
	static $autumnal_equinox_days;
	if(!isset($autumnal_equinox_days)) {
		$autumnal_equinox_days = array(
			1925 => '09-23',
			1926 => '09-24',
			1927 => '09-24',
			1928 => '09-23',
			1929 => '09-23',
			1930 => '09-24',
			1931 => '09-24',
			1932 => '09-23',
			1933 => '09-23',
			1934 => '09-24',
			1935 => '09-24',
			1936 => '09-23',
			1937 => '09-23',
			1938 => '09-24',
			1939 => '09-24',
			1940 => '09-23',
			1941 => '09-23',
			1942 => '09-24',
			1943 => '09-24',
			1944 => '09-23',
			1945 => '09-23',
			1946 => '09-24',
			1947 => '09-24',
			1948 => '09-23',
			1949 => '09-23',
			1950 => '09-23',
			1951 => '09-24',
			1952 => '09-23',
			1953 => '09-23',
			1954 => '09-23',
			1955 => '09-24',
			1956 => '09-23',
			1957 => '09-23',
			1958 => '09-23',
			1959 => '09-24',
			1960 => '09-23',
			1961 => '09-23',
			1962 => '09-23',
			1963 => '09-24',
			1964 => '09-23',
			1965 => '09-23',
			1966 => '09-23',
			1967 => '09-24',
			1968 => '09-23',
			1969 => '09-23',
			1970 => '09-23',
			1971 => '09-24',
			1972 => '09-23',
			1973 => '09-23',
			1974 => '09-23',
			1975 => '09-24',
			1976 => '09-23',
			1977 => '09-23',
			1978 => '09-23',
			1979 => '09-24',
			1980 => '09-23',
			1981 => '09-23',
			1982 => '09-23',
			1983 => '09-23',
			1984 => '09-23',
			1985 => '09-23',
			1986 => '09-23',
			1987 => '09-23',
			1988 => '09-23',
			1989 => '09-23',
			1990 => '09-23',
			1991 => '09-23',
			1992 => '09-23',
			1993 => '09-23',
			1994 => '09-23',
			1995 => '09-23',
			1996 => '09-23',
			1997 => '09-23',
			1998 => '09-23',
			1999 => '09-23',

			2000 => '09-23',
			2001 => '09-23',
			2002 => '09-23',
			2003 => '09-23',
			2004 => '09-23',
			2005 => '09-23',
			2006 => '09-23',
			2007 => '09-23',
			2008 => '09-23',
			2009 => '09-23',
			2010 => '09-23',
			2011 => '09-23',
			2012 => '09-22',
			2013 => '09-23',
			2014 => '09-23',
			2015 => '09-23',
		);
	}
//	return isset($autumnal_equinox_days[$y]) ? ($autumnal_equinox_days[$y] == $m_d) : null;
	return $m_d == (isset($autumnal_equinox_days[$y]) ? $autumnal_equinox_days[$y] : get_equinox_day_by_calc($y, 'autumnal'));
}

function get_equinox_day_by_calc($y, $va) {

//	1太陽年は（西暦2000年において）365.24219日（365.24219040日）となっており、100年間で約0.53秒ずつ短くなっている。
//	2000年の太陽の春分点通過日
//	3月20.69115日
//	2000年の太陽の秋分点通過日
//	9月23.09日

	switch($va) {
	case 'vernal':
		$equinox = 953537715.36;	// strtotime('2000-03-20') + (60 * 60 * 24 * 0.69115)
		break;
	case 'autumnal':
		$equinox = 969642576.00;	// strtotime('2000-09-23') + (60 * 60 * 24 * 0.09)
		break;
	}

	return date('m-d', 
		(int)($equinox 										// 2000年の春(秋)分点
		+ (3155692525056 * ($y - 2000) / 100000) 			// 2000年から太陽年の計算
		+ (53 * (array_sum(range(0, $y - 2000))) / 10000))	// 太陽年の誤差修正（100年間で約0.53短くなりつつある）
	);

}

?>