﻿/*
 * jpCalendar 1.0 - 日本カレンダー
 *
 * Copyright (c) 2007 Zhiwei Ou (ouzhiwei@gmail.com)
 * licensed under the GPL licenses.
 *
 * 参考：
 *  http://ja.wikipedia.org/wiki/日本のこよみ
 *  http://www.kumamotokokufu-h.ed.jp/kumamoto/bungaku/wa_seireki.html
 *
 * $Date: 2007-08-03 $
 * $Rev: $
 */

//*******************************************************
// 各月の別名
//*******************************************************
var arrMonthAlias = {
	1: '睦月（むつき）',
	2: '如月 または 衣更着（きさらぎ）',
	3: '弥生（やよい）',
	4: '卯月（うづき）',
	5: '皐月 または 早月（さつき）',
	6: '水無月（みなづき）',
	7: '文月（ふみつき）',
	8: '葉月（はづき）',
	9: '長月（ながつき）',
	10: '神無月（かんなづき）、出雲地方では神有月（かみありつき）',
	11: '霜月（しもつき）',
	12: '師走（しわす）'
};

//*******************************************************
// 二十四節気、雑節
//*******************************************************
var arrDayAlias = {
	'1.5': '寒の入り（かんのいり）、小寒（しょうかん）',
	'1.17': '冬の土用（どよう）',
	'1.20': '大寒（だいかん）',
	'2.3': '節分（せつぶん）',
	'2.4': '立春（りっしゅん）',
	'2.19': '雨水（うすい）',
	'3.6': '啓蟄（けいちつ）',
	'3.16': '春の社日（しゃにち）',
	'3.18': '春彼岸（はるひがん）',
	'3.21': '春分（しゅんぶん）',
	'4.5': '清明（せいめい）',
	'4.17': '春の土用（どよう）',
	'4.20': '穀雨（こくう）',
	'5.2': '八十八夜（はちじゅうはちや）',
	'5.6': '立夏（りっか）',
	'5.21': '小満（しょうまん）',
	'6.6': '芒種（ぼうしゅ）',
	'6.11': '入梅（にゅうばい）',
	'6.21': '夏至（げし）',
	'7.2': '半夏生（はんげしょう）',
	'7.7': '小暑（しょうしょ）',
	'7.15': '中元（ちゅうげん）、盆（ぼん）',
	'7.20': '夏の土用（どよう）',
	'7.23': '大暑（たいしょ）',
	'8.8': '立秋（りっしゅう）',
	'8.23': '処暑（しょしょ）',
	'9.1': '二百十日（にひゃくとおか）',
	'9.8': '白露（はくろ）',
	'9.11': '二百二十日（にひゃくはつか）',
	'9.20': '秋彼岸（あきひがん）',
	'9.22': '秋の社日（しゃにち）',
	'9.23': '秋分（しゅうぶん）',
	'10.8': '寒露（かんろ）',
	'10.20': '秋の土用（どよう）',
	'10.23': '霜降（そうこう）',
	'11.7': '立冬（りっとう）',
	'11.22': '小雪（しょうせつ）',
	'12.7': '大雪（たいせつ）',
	'12.22': '冬至（とうじ）'
};

//*******************************************************
// 黄道十二星座
//*******************************************************
var arrZodiac = [
	'牡羊座（おひつじ座）',
	'牡牛座（おうし座）',
	'双子座（ふたご座）',
	'蟹座（かに座）',
	'獅子座（しし座）',
	'乙女座（おとめ座）',
	'天秤座（てんびん座）',
	'蠍座（さそり座）',
	'射手座（いて座）',
	'山羊座（やぎ座）',
	'水瓶座（みずがめ座）',
	'魚座（うお座）'
];

//*******************************************************
// 日本語年名前の取得
//*******************************************************
function getJpYearName(numYear) {
	var arrJNum = new Array('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九');
	var strYear = numYear + '';
	var strName = '';
	for(var i = 0; i < strYear.length; i++) {
		var n = parseInt(strYear.charAt(i));
		strName += arrJNum[n];
	}
	return strName + '年';
}

//*******************************************************
// 和暦年号の取得(明治から)
//*******************************************************
function getWarekiYearName(numYear, numMonth, numDay) {
	var today = new Date();
	numCurYear = today.getFullYear();
	numCurMon = today.getMonth() + 1;
	numCurDay = today.getDate();
	
	strDate = '' + numYear + ((numMonth < 10) ? '0' : '') + numMonth + ((numDay < 10) ? '0' : '') + numDay;
	strCurDate = '' + numCurYear + ((numCurMon < 10) ? '0' : '') + numCurMon + ((numCurDay < 10) ? '0' : '') + numCurDay;

	var arrWareki = [
		{'name': '明治', 'start': '18680908', 'end': '19120730'},
		{'name': '大正', 'start': '19120730', 'end': '19261225'},
		{'name': '昭和', 'start': '19261225', 'end': '19890107'},
		{'name': '平成', 'start': '19890108', 'end': strCurDate}
	];
	
	var strName = '';
	for(var i=0; i<arrWareki.length; i++) {
		if(arrWareki[i]['start'] <= strDate && strDate <= arrWareki[i]['end']) {
			var strAnd = (strName == '') ? '' : '年&nbsp;';
			var numBaseYear = parseInt(arrWareki[i]['start'].substring(0,4));
			strName += strAnd + arrWareki[i]['name'] + (numYear - numBaseYear + 1);
		}
	}

	return (strName == '') ? '' : strName + '年';
}

//*******************************************************
// 日本語月名前の取得
//*******************************************************
function getJpMonthName(numMonth) {
	var arrJNum = new Array('', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二');
	return arrJNum[numMonth] + '月';
}

//*******************************************************
// 指定月の日数を取得
//*******************************************************
function getLastDay(numYear, numMonth) {
	with (new Date(numYear, numMonth, 1, 12)) {
		setDate(0) ; 
		return getDate();
	}
}

//*******************************************************
// 国民の休日
//*******************************************************
function getJapanHoliDay(numYear, strKey1, strKey2) {
	var strTitle = '';
	//何月何日
	switch( strKey1 ) {
		case '1.1':
			strTitle = (numYear >= 1948) ? '元日' : '';
			break;
		case '1.15':
			strTitle = (numYear >= 1948 && numYear < 2000) ? '成人の日' : '';
			break;
		case '2.11':
			strTitle = (numYear >= 1966) ? '建国記念の日' : '';
			break;
		case '3.21':
			strTitle = (numYear >= 1948) ? '春分の日' : '';
			break;
		case '4.29':
			strTitle = (numYear >= 2007) ? '昭和の日' : 
							( (numYear >= 1989 && numYear < 2007) ? 'みどりの日' : 
								((numYear >= 1948 && numYear < 1989) ? '天皇誕生日' : '') );
			break;
		case '5.3':
			strTitle = (numYear >= 1948) ? '憲法記念日' : '';
			break;
		case '5.4':
			strTitle = (numYear >= 2007) ? 'みどりの日' : '';
			break;
		case '5.5':
			strTitle = (numYear >= 1948) ? 'こどもの日' : '';
			break;
		case '7.20':
			strTitle = (numYear >= 1995 && numYear < 2003) ? '海の日' : '';
			break;
		case '9.15':
			strTitle = (numYear >= 1966 && numYear < 2003) ? '敬老の日' : '';
			break;
		case '9.23':
			strTitle = (numYear >= 1948) ? '秋分の日' : '';
			break;
		case '10.10':
			strTitle = (numYear >= 1966 && numYear < 2000) ? '体育の日' : '';
			break;
		case '11.3':
			strTitle = (numYear >= 1948) ? '文化の日' : '';
			break;
		case '11.23':
			strTitle = (numYear >= 1948) ? '勤労感謝の日' : '';
			break;
		case '12.23':
			strTitle = (numYear >= 1989) ? '天皇誕生日' : '';
			break;
		default:
			break;
	}
	
	//何月何週何日
	var strAnd = (strTitle == '') ? '' : '<br />';
	switch( strKey2 ) {
		case '1.w2.1':
			strTitle += (numYear >= 2000) ? strAnd + '成人の日' : '';
			break;
		case '7.w3.1':
			strTitle += (numYear >= 2003) ? strAnd + '海の日' : '';
			break;
		case '9.w3.1':
			strTitle += (numYear >= 2003) ? strAnd + '敬老の日' : '';
			break;
		case '10.w2.1':
			strTitle += (numYear >= 2000) ? strAnd + '体育の日' : '';
			break;
		default:
			break;
	}

	return strTitle;
}

//*******************************************************
// 復活祭の計算
//*******************************************************
function getEaster(numYear) {
    var golden = numYear % 19;
    var fullmoon = (golden*(30 - 11)+15) % 30;
    if (numYear > 1582) {
        var century = Math.floor((numYear - 1500)/100);
        var adjust = Math.floor(century/25)*8 + Math.min(8,Math.floor((century%25)/3)) + 3;
        fullmoon = (fullmoon + Math.floor(numYear/100) -Math.floor(numYear/400) - 2 - adjust) % 30;
        
        if (fullmoon == 28 && golden >= 11) {
        	// 第２エパクト補正
        	fullmoon--;
        }else if (fullmoon > 28) {
        	// 4/26 -> 4/25補正
        	fullmoon = 28;
        }
    }
	
	numMonth = 3;
    var adjust = numYear <= 1582 ? 2 : Math.floor(numYear/100) - Math.floor(numYear/400);
    wDay = (numYear + Math.floor(numYear/4) - adjust + Math.floor((13 * numMonth + 8)/5) + 21 + fullmoon) % 7;

    pascha = fullmoon + 7 - wDay

    var numDay = 21 + pascha;
    if (numDay > 31) {
        numMonth++; 
        numDay -= 31;
    }
    
    return numMonth + '.' + numDay;
}

//*******************************************************
// 西洋の祝日
//*******************************************************
var arrEaster = new Array();
function getWestHoliDay(numYear, strKey1, strKey2) {
	var strTitle = '';
	
	//重複計算しないため，グローバル配列に保存する
	if(!arrEaster[numYear]) {
		arrEaster[numYear] = getEaster(numYear);
	}
	//何月何日
	switch( strKey1 ) {
		case arrEaster[numYear]:
			strTitle = '復活祭';
			break;
		case '2.14':
			strTitle = 'バレンタインデー';
			break;
		case '4.1':
			strTitle = 'エイプリルフール';
			break;
		case '5.1':
			strTitle = 'メーデー(労働祭)';
			break;
		case '10.31':
			strTitle = 'ハロウィン';
			break;
		case '12.24':
			strTitle = 'クリスマス・イヴ';
			break;
		case '12.25':
			strTitle = 'クリスマス';
			break;
		default:
			break;
	}
	
	//何月何週何日
	var strAnd = (strTitle == '') ? '' : '<br />';
	switch( strKey2 ) {
		case '5.w2.0':
			strTitle += strAnd + (numYear >= 1907 ? '母の日' : '');
			break;
		case '6.w3.0':
			strTitle += strAnd + (numYear >= 1910 ? '父の日' : '');
			break;
		case '11.w4.4':
			strTitle += strAnd + (numYear >= 1924 ? '感謝祭' : '');
			break;
		default:
			break;
	}

	return strTitle;
}

//*******************************************************
// 星座の取得
//*******************************************************
function getZodiac(numMonth, numDay) {
	var numTmp = numMonth * 100 + numDay;
	var numIndex;

	if ((numTmp >= 321) && (numTmp <= 419)) {
		numIndex = 0;
	} else if ((numTmp >= 420) && (numTmp <= 520)) {
		numIndex = 1;
	} else if ((numTmp >= 521) && (numTmp <= 621)) {
		numIndex = 2;
	} else if ((numTmp >= 622) && (numTmp <= 722)) {
		numIndex = 3;
	} else if ((numTmp >= 723) && (numTmp <= 822)) {
		numIndex = 4;
	} else if ((numTmp >= 823) && (numTmp <= 922)) {
		numIndex = 5;
	} else if ((numTmp >= 923) && (numTmp <= 1022)) {
		numIndex = 6;
	} else if ((numTmp >= 1023) && (numTmp <= 1121)) {
		numIndex = 7;
	} else if ((numTmp >= 1122) && (numTmp <= 1221)) {
		numIndex = 8;
	} else if ((numTmp >= 1222) || (numTmp <= 119)) {
		numIndex = 9;
	} else if ((numTmp >= 120) && (numTmp <= 218)) {
		numIndex = 10;
	} else if ((numTmp >= 219) && (numTmp <= 320)) {
		numIndex = 11;
	} else {
		return '';
	}
	
	return arrZodiac[numIndex];
}

//*******************************************************
// 指定年月のカレンダーのHTML作成
//*******************************************************
function getCalendarHtml(numYear, numMonth) {
	var strYear = numYear + '年';
	var strMonth = ( numMonth < 10 ) ? '0' + numMonth + '月' : '' + numMonth + '月';
	
	var startDate = new Date(numYear, numMonth - 1, 1, 0, 0, 0);
	var numOffset = startDate.getDay() - 1;
	var numLastDay = getLastDay(numYear, numMonth);

	var strAnd = '<br />';

	var strMonthTip = getJpYearName(numYear) + getJpMonthName(numMonth) + strAnd + arrMonthAlias[numMonth];

	//月カレンダーのHTML
	var strHtml = '	    <table cellpadding="2" cellspacing="2" border="0">\n'
				+ '	      <tr>\n'
				+ '	        <td colspan="7" title="' + strMonthTip + '"><center>\n'
				+ '	          <b>' + strYear + strMonth + '</b>\n'
				+ '	        </center></td>\n'
				+ '	      </tr>\n'
				+ '	      <tr>\n'
				+ '	        <th align="right"><font color="#DD0022">日</font></th>\n'
				+ '	        <th align="right">月</th>\n'
				+ '	        <th align="right">火</th>\n'
				+ '	        <th align="right">水</th>\n'
				+ '	        <th align="right">木</th>\n'
				+ '	        <th align="right">金</th>\n'
				+ '	        <th align="right"><font color="#DD0022">土</font></th>\n'
				+ '	      </tr>\n';

	var numCount = 0;
	var arrWdayCnt = [0, 0, 0, 0, 0, 0, 0];
	for( var iRow = 0; iRow < 6; iRow++) {
		strHtml += '	      <tr>\n';
		for( var iCol = 0; iCol < 7; iCol++) {
			var numDay = numCount - numOffset;

			var strText = ''
			var strDayTip = '';
			var strBgColor = '';
			var strTextColor = (iCol == 0 || iCol == 6) ? '#DD0022' : '';
			if( numDay > 0 && numDay <= numLastDay ) {
				strText = '' + numDay;

				var strYearName = getWarekiYearName(numYear, numMonth, numDay);
				if(strYearName == '' ) {
					strYearName = numYear + '年';
				}
				strDayTip = strYearName + numMonth + '月' + numDay + '日';

				var numWeek = iRow + 1;
				var numWeekDay = (new Date(numYear, numMonth - 1, numDay, 0, 0, 0)).getDay();
				arrWdayCnt[numWeekDay] += 1;

				var strKey1 = numMonth + '.' + numDay;
				var strKey2 = numMonth + '.w' + arrWdayCnt[numWeekDay] + '.' + numWeekDay;
					
				// 二十四節気、雑節
				if( arrDayAlias[strKey1] ) {
					strDayTip += strAnd + arrDayAlias[strKey1];
					strTextColor = '#336600';
					strBgColor = '#F1FAE8';
				}

				//西洋の祝日
				var strWestHoliDay = getWestHoliDay(numYear, strKey1, strKey2);
				if( strWestHoliDay != '') {
					strDayTip += strAnd + strWestHoliDay;
					strTextColor = '#660099';
					strBgColor = '#F6ECF6';
				}

				//国民の休日
				var strJapanHoliDay = getJapanHoliDay(numYear, strKey1, strKey2);
				if( strJapanHoliDay != '') {
					strDayTip += strAnd + strJapanHoliDay;
					strTextColor = '#DD0022';
					strBgColor = '#FFE4E1';
				}
				
				//黄道十二星座
				var strZodiac = getZodiac(numMonth, numDay);
				strDayTip += strAnd + strAnd + '【星座】';
				strDayTip += strAnd + strZodiac;
					
			} else {
				strText = '&nbsp;';
			}

			strTextColor = (strTextColor == '') ? '#000000' : strTextColor;
			
			strHtml +='	        <td title="'+ strDayTip + '" bgcolor="'+ strBgColor + '" align="right"><font color="' + strTextColor + '">'+ strText +'</font></td>\n';
			numCount++;
		}
		strHtml += '	      </tr>\n';
	}
	
	strHtml += '	    </table>\n';
    return strHtml;
}
