/* ================================================== */
/* 汎用 祝祭日計算                                    */
/* calcHoliday.js                                     */
/* 【注意】必ずjquery-1.6.2.min.js の後に実行すること */
/*                                                    */
/*                                                    */
/* 来歴---------------------------------------------- */
/* 2011/10/01　新規作成                               */
/*                                                    */
/* ================================================== */




/* 初期処理：「国民の祝日」の定義 */
/* 【注意事項】春分・秋分の日は1980年～2100年まで有効。「国民の祝日」については「国民の祝日に関する法律（平成一七年五月二〇日法律第四三号）」を適用。（月を跨ぐ振替休日は考慮（存在）しない） 詳細は内閣府の法令を参照*/
/* 【設定内容】2次元配列の最初の要素は「月」であり、次の要素は「日」となる。ただし、毎年変動する祝日に関しては先頭に「c」を入れ、次の文字列は「第n月曜日」を意味する。「c2」の場合は「変動する祝日で、第2月曜日」を意味する。なお、「c0」は春分・秋分にのみ適用される（固定値） */
var inputHoliday = new Array();					// 入力：「国民の祝日」一覧(char, 2次元配列[月][日 又は 第n月曜日])
inputHoliday[0]  = new Array('1','1');			// 入力：「元旦」の月・日(char)
inputHoliday[1]  = new Array('1',"c2");			// 入力：「成人の日」の月・日(char)
inputHoliday[2]  = new Array('2','11');			// 入力：「建国記念の日」の月・日(char)
inputHoliday[3]  = new Array('3',"c0");			// 入力：「春分の日」の月・日(char)
inputHoliday[4]  = new Array('4','29');			// 入力：「昭和の日」の月・日(char)
inputHoliday[5]  = new Array('5','3');			// 入力：「憲法記念日」の月・日(char)
inputHoliday[6]  = new Array('5','4');			// 入力：「みどりの日」の月・日(char)
inputHoliday[7]  = new Array('5','5');			// 入力：「こどもの日」の月・日(char)
inputHoliday[8]  = new Array('7',"c3");			// 入力：「海の日」の月・日(char)
inputHoliday[9]  = new Array('9',"c3");			// 入力：「敬老の日」の月・日(char)
inputHoliday[10] = new Array('9',"c0");			// 入力：「秋分の日」の月・日(char)
inputHoliday[11] = new Array('10',"c2");		// 入力：「体育の日」の月・日(char)
inputHoliday[12] = new Array('11','3');			// 入力：「文化の日」の月・日(char)
inputHoliday[13] = new Array('11','23');		// 入力：「勤労感謝の日」の月・日(char)
inputHoliday[14] = new Array('12','23');		// 入力：「天皇誕生日」の月・日(char)




/* ============================================ */
/* =============== 日付計算処理 =============== */
/* ============================================ */


/* 計算処理：休日判定処理メインストリーム 返り値：boolean  */
/* 【注意事項】引数の"inputMonth"には"-1"を行わないこと */
function calcHolidayMain(inputYear,inputMonth,inputDay){

	//当日が日曜日かどうか
	if(calcSunday(inputYear,inputMonth,inputDay)){
		return true;
	}
//alert('当日は日曜日ではない');

	//当日が「国民の祝日」かどうか
	if(calcALLHoliday(inputYear,inputMonth,inputDay)){
		return true;
	}
//alert('当日は「国民の祝日」ではない');

	var tmpBaseDay = 1;

	//当日が1日ではないか
	if(inputDay >= tmpBaseDay){
//alert('当日は「1日」ではない');

		//前日が「国民の祝日」かどうか
		if(calcALLHoliday(inputYear,inputMonth,(inputDay - tmpBaseDay)) == true){
//alert('前日は「国民の祝日」');
			//前日が日曜日かどうか
			if(calcSunday(inputYear,inputMonth,(inputDay - tmpBaseDay)) == true){
//alert('当日は振り替え休日');
				return true;

			//翌日が「国民の祝日」かどうか
			}else if(calcALLHoliday(inputYear,inputMonth,(inputDay + tmpBaseDay)) == true){
//alert('当日は「国民の休日」');
				return true;

			//前日以前から連続して「国民の祝日」であり、かつ、どれかの日が日曜日であるか
			}else if(inputDay >= tmpBaseDay + 1){
				if(calcALLHoliday(inputYear,inputMonth,(inputDay - (tmpBaseDay + 1))) == true){
					if(calcSunday(inputYear,inputMonth,(inputDay - (tmpBaseDay + 1))) == true){
//alert('前々日が祝日＆日曜なので、当日は振り替え休日');
						return true;
					}else if(calcALLHoliday(inputYear,inputMonth,(inputDay - (tmpBaseDay + 2))) == true){
						if(calcSunday(inputYear,inputMonth,(inputDay - (tmpBaseDay + 2))) == true){
//alert('前々々日が祝日＆日曜で、前々日が祝日なので、当日は振り替え休日');
							return true;
							/* 現行の法律では4連続以上の祝日の連続はありえないため、4日以上の祝日の連続の判定は行わない */
						}
					}
				}
			}

		}
//alert('前日は「国民の祝日」ではない');

	}

//alert('当日は休日ではない');
	return false;
}


/* 計算処理：全ての休日判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には"-1"を行わないこと */
function calcALLHoliday(getInputYear,getInputMonth,getInputDay){

	//「国民の祝日」の定義に引数の月のデータがあるかどうか
	for(var i=0;i<inputHoliday.length;i++){
		if(inputHoliday[i][0] == getInputMonth){
			//「国民の祝日」の判定
			if(calcHoliday(i,getInputYear,getInputMonth,getInputDay) == true){
				return true;
			}
		}
	}

	return false;
}


/* 計算処理：「国民の祝日」判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcHoliday(getNum,getInputYear,getInputMonth,getInputDay){

	//「国民の祝日」が固定日の場合
	if(inputHoliday[getNum][1].indexOf("c") == -1){
		if(calcFixHoliday(getNum,getInputMonth,getInputDay)){
//alert('「国民の祝日」:固定');
			return true;
		}

	//「国民の祝日」が変動日の場合
	}else if(inputHoliday[getNum][1].indexOf("c") > -1){

		//第何月曜日か取得
		var tmpOrderMonday = inputHoliday[getNum][1].slice(-1);

		//春分・秋分の日ではない場合
		if(tmpOrderMonday != 0){
			if(calcChangeHoliday(getInputYear,getInputMonth,getInputDay,tmpOrderMonday)){
//alert('「国民の祝日」:変動');
				return true;
			}

		//春分の日の判定
		}else if(getInputMonth == 3){
			if(calcVernal(getInputYear,getInputMonth,getInputDay)){
//alert('「春分の日」');
				return true;
			}

		//秋分の日の判定
		}else if(getInputMonth == 9){

			if(calcAutumnal(getInputYear,getInputMonth,getInputDay)){
//alert('「秋分の日」');
				return true;
			}
		}
	}

	return false;
}


/* 計算処理：固定日である「国民の祝日」判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcFixHoliday(getNum,getInputMonth,getInputDay){
	if(inputHoliday[getNum][1] == getInputDay){
		return true;
	}
	return false;
}

/* 計算処理：変動日である「国民の祝日」判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcChangeHoliday(getInputYear,getInputMonth,getInputDay,orderMonday){
	if(getInputDay == (calcFirstMonday(getInputYear, getInputMonth) + ((orderMonday - 1) * 7))){
		return true;
	}
	return false;
}


/* 計算処理：春分の日判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcVernal(getInputYear,getInputMonth,getInputDay){
	if(getInputDay == parseInt(20.8431 + 0.242194 * (getInputYear - 1980) - parseInt((getInputYear - 1980) / 4))){
		return true;
	}
	return false;
}


/* 計算処理：秋分の日判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcAutumnal(getInputYear,getInputMonth,getInputDay){
	if(getInputDay == parseInt(23.2488 + 0.242194 * (getInputYear - 1980) - parseInt((getInputYear - 1980) / 4))){
		return true;
	}
	return false;
}


/* 計算処理：日曜日判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcSunday(getInputYear,getInputMonth,getInputDay){
	if (new Date(getInputYear, (getInputMonth - 1), getInputDay).getDay() == 0){
		return true;
	}
	return false;
}

/* 計算処理：土曜日判定処理 返り値：boolean  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcSaturday(getInputYear,getInputMonth,getInputDay){
	if (new Date(getInputYear, (getInputMonth - 1), getInputDay).getDay() == 6){
		return true;
	}
	return false;
}

/* 計算処理：第1月曜日判定処理 返り値：int  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcFirstMonday(getInputYear,getInputMonth){
	for(var tmpDay = 1; tmpDay < 8; tmpDay++){
		if(new Date(getInputYear, (getInputMonth - 1), tmpDay).getDay() == 1){
			break;
		}
	}
	return tmpDay;
}

/* 計算処理：第2金曜日判定処理 返り値：int  */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcSecondFriday(getInputYear,getInputMonth){
	for(var tmpDay = 1; tmpDay < 8; tmpDay++){
		if(new Date(getInputYear, (getInputMonth - 1), tmpDay).getDay() == 5){
			break;
		}
	}
	return (tmpDay + 7);
}

/* 計算処理：月末日判定処理 返り値：int  */
function calcMonthLastDay(getInputYear,getInputMonth){

	var outputMonthFinalDay = 31;		//月の最後の日(int)
	var tmpLeapYear         = false;	//入力された年が閏年か否か(boolean)

	//閏年判定
	if((getInputYear % 4 == 0 && getInputYear % 100 != 0) || getInputYear % 400 == 0){
		tmpLeapYear = true;
	}

	//月によって表示する日数を決める
	switch(getInputMonth){
		case 2:
			if(tmpLeapYear){	//閏年を考慮
				outputMonthFinalDay = 29;
				break;
			}else{
				outputMonthFinalDay = 28;
				break;
			}
		case 4:
			outputMonthFinalDay = 30;
			break;
		case 6:
			outputMonthFinalDay = 30;
			break;
		case 9:
			outputMonthFinalDay = 30;
			break;
		case 11:
			outputMonthFinalDay = 30;
			break;
		default:
			outputMonthFinalDay = 31;
			break;
	}
	
	return outputMonthFinalDay;

}


/* 計算処理：土曜・休日判定処理 返り値：boolean */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcBackWeekday(getInputTime){
	var tmpInputTime = new Date();
	tmpInputTime.setTime(getInputTime);

	if(calcHolidayMain(tmpInputTime.getFullYear(),(tmpInputTime.getMonth() + 1),tmpInputTime.getDate())){
		return true;
	}else if(calcSaturday(tmpInputTime.getFullYear(),(tmpInputTime.getMonth() + 1),tmpInputTime.getDate())){
		return true;
	}
	return false;
}


/* 計算処理:入力された日数後の日付の計算　引数：1=年, 2=月, 3=日, 4=経過日　返り値：計算後の日付オブジェクト */
/* 【注意事項】引数の"getInputMonth"には予め"-1"を行わないこと */
function calcPassDays(getInputYear,getInputMonth,getInputDay,getAddDay){
	var tmpDate    = new Date(getInputYear, (getInputMonth - 1), getInputDay);
	tmpDate.setTime( tmpDate.getTime() + (getAddDay * 86400000) );
	return tmpDate;
}


