<!--
///////////////////////////////////
// 旧暦計算プログラム基本ルーチン
///////////////////////////////////

// 1999-2030 Old2New パラメータ
var nyymin = 1999;
var nyymax = 2030;
var o2ntbl = [[611,2350]	,[468,3222]	,[316,7317]	,[559,3402]	,[416,3493]
	,[288,2901]	,[520,1388]	,[384,5467]	,[637,605]	,[494,2349]	,[343,6443]
	,[585,2709]	,[442,2890]	,[302,5962]	,[533,2901]	,[412,2741]	,[650,1210]
	,[507,2651]	,[369,2647]	,[611,1323]	,[468,2709]	,[329,5781]	,[559,1706]
	,[416,2773]	,[288,2741]	,[533,1206]	,[383,5294]	,[624,2647]	,[494,1319]
	,[356,3366]	,[572,3475]	,[442,1450]];

var nmdays = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var otbl = new Array(14);

// 簡単なエラーチェック
// tflag : 1 旧暦 , not 1 新暦
function ymdCheck(yy,mm,dd,tflag) {
	var flag = true;

	if ((yy < nyymin + 1) || (yy > nyymax)) flag = false;
	if (tflag == 1) {
		if ((Math.abs(mm) < 1) || (Math.abs(mm) > 12)) flag = false;
		if ((dd < 1) || (dd > 30)) flag = false;
	} else {
		if ((mm < 1) || (mm > 12)) flag = false;
		if ((dd < 1) || (dd > 31)) flag = false;
	}

	if (!flag) {
		alert('入力値異常。チェックして (' + yy + '/' + mm + '/' + dd + ')');
	}
	return flag;
}

// 旧暦→新暦変換
// 戻り値は Array(nyy,nmm,ndd) 
// Errorなら、 Array(0,0,0) を返す
function get_O2N(oyy,omm,odd) {
	var nyy,nmm,ndd,tmp,DofNyy;

	if (!ymdCheck(oyy,omm,odd,1)) return Array(0,0,0);	// 入力値のチェック（1:旧暦）
	TblExpand(oyy);

	DofNyy = -1;
	for (var i = 0; i <= 13 ; i++) {
		if (otbl[i][1] == omm) {
			DofNyy = otbl[i][0] + odd - 1;
			break;
		}
	}
	if (DofNyy < 0) {
		return Array(0,0,0);	// 該当する旧暦日無し
	}

	nyy = oyy;
	tmp = 365 + LeapYear(nyy);
	if (DofNyy > tmp) {
		DofNyy -= tmp;
		nyy++;
	}

	ndd = -1;
	for (nmm = 12; nmm >= 1 ; nmm--) {
		tmp = NumberDays(nyy,nmm,1);
		if (DofNyy >= tmp) {
			ndd = DofNyy - tmp + 1;
			break;
		}
	}
	if (ndd < 0) {
		return Array(0,0,0);	// 異常な日付？
	}
	return Array(nyy,nmm,ndd);
}

// 新暦→旧暦変換
// 戻り値は Array(nyy,nmm,ndd,uruu)   ・・・ uruu : "閏" or "";
// Errorなら、 Array(0,0,0,"") を返す
function get_N2O(nyy,nmm,ndd) {
	var oyy,omm,odd,uruu,DofNyy;

	if (!ymdCheck(nyy,nmm,ndd,0)) return Array(0,0,0,"");	// 入力値チェック（0:新暦）
	DofNyy = NumberDays(nyy,nmm,ndd);
	oyy = nyy;
	TblExpand(oyy);
	if (DofNyy < otbl[0][0]) {
		oyy--;
		DofNyy += 365 + LeapYear(oyy);
		TblExpand(oyy);
	}

	for (var i = 12; i >= 0 ; i--) {
		if (otbl[i][1] != 0) {
			if (otbl[i][0] <= DofNyy) {
				omm = otbl[i][1];
				odd = DofNyy - otbl[i][0] + 1;
				break;
			}
		}
	}
	if (omm < 0) {
		uruu = '閏';
		omm = -omm;
	} else {
		uruu = '';
	}
	return Array(oyy,omm,odd,uruu);
}

// グレゴリウス暦閏年判定。閏年なら 1, 平年なら 0
function LeapYear(yy) {
	var ans = 0;
	if ((yy % 4) == 0) ans = 1;
	if ((yy % 100) == 0) ans = 0;
	if ((yy % 400) == 0) ans = 1;
	return ans;
}

// 新暦年初からの通日 1/1 = 1
function NumberDays(yy,mm,dd) {
	nmdays[1] = 28 + LeapYear(yy);

	var days = dd;
	for (var m = 1; m < mm ; m++) {
		days += nmdays[m - 1];
	}
	return days;
}

// 旧暦・新暦テーブル(otbl)作成
function TblExpand(yy) {
	var ommax,days,uruu,bit;

	days = o2ntbl[yy - nyymin][0];
	bit  = o2ntbl[yy - nyymin][1];
	uruu = days % 13;	// 閏月抽出。無ければ 0
	days = Math.floor(days / 13 + 0.001);	// 旧暦年初の新暦年初からの日数

	otbl[0] = Array(days,1);	// 旧暦正月の通日と、月数
	if (uruu == 0) {
		bit *= 2;	// 閏無しなら 12ヶ月
		ommax = 12;
	} else {
		ommax = 13;
	}

	for (var i = 1; i <= ommax; i++) {
		otbl[i] = Array(otbl[i-1][0]+29, i+1);
		if (bit >= 4096) {
			otbl[i][0]++;	// 大の月
		}
		bit = (bit % 4096) * 2;
	}
	otbl[ommax][1] = 0;	// テーブルの終わり＆旧暦翌年年初

	if (ommax > 12) {// 閏月のある年
		for (var i = uruu + 1; i < 13 ; i++) {
			otbl[i][1] = i;
		}
		otbl[uruu][1] = -uruu;	// 識別のため閏月はマイナスで記録
	} else {
		otbl[13] = Array(0,0);	// 使ってないけどエラー防止で。
	}
}

///////////////////////////////////////
// サンプルプログラムのためのコード
///////////////////////////////////////
var odate = new Array(4);
var Rokuyou = new Array('大安','赤口','先勝','友引','先負','仏滅');

function Startup() {
//	var nowd = new Date;
//	with (document.YMD) {
//		SYY.value = nowd.getFullYear();
//		SMM.value = nowd.getMonth() + 1;
//		SDD.value = nowd.getDate();
//	}
	New2Old();
}

// 新暦→旧暦
function New2Old() {
	cInput();
	with (document.YMD) {
		var nyy = SYY.value * 1;
		var nmm = SMM.value * 1;
		var ndd = SDD.value * 1;

	  var ans = get_N2O(nyy,nmm,ndd);	// 年、月、日、閏　の順に答えが返る。
		ANS2.value = '****';
		ANS16.value = '****';
		ANS26.value = '****';
		if (ans[0] > 0) {
			ANS1.value = '旧暦 ' + ans[0] + '年' + ans[3] + ans[1] + '月' + ans[2] + '日';
			ANS16.value = Rokuyou[(ans[1] + ans[2]) % 6];	// 六曜
		} else {
			ANS1.value = '変換不能。入力をチェック！';
		}
	}
}

// 旧暦→新暦
function Old2New() {
	cInput();
	with (document.YMD) {
		var oyy = SYY.value * 1;
		var omm = SMM.value * 1;
		var odd = SDD.value * 1;

	  var ans = get_O2N(oyy,omm,odd);	// 年、月、日の順に答えが返る。
		ANS2.value = '**** '
		ANS16.value = '****';
		ANS26.value = '****';
		if (ans[0] > 0) {
			ANS1.value = '新暦(1) ' + ans[0] + '年' + ans[1] + '月' + ans[2] + '日';
			ANS16.value = Rokuyou[(omm + odd) % 6];	// 六曜
		} else {
			ANS1.value = '変換不能。入力をチェック！';
			return;
		}

		ans = get_O2N(oyy,-omm,odd);	// 閏月の場合を考慮
		if (ans[0] > 0) {
			ANS2.value = '新暦(2) ' + ans[0] + '/' + ans[1] + '/' + ans[2] + ' (旧暦閏月)';
			ANS26.value = Rokuyou[(omm + odd) % 6];	// 六曜
		}
	}
}

// 異常な入力値に対する対処（ちょっとだけ）
function cInput() {
	with (document.YMD) {
		SYY.value = Math.floor(Math.abs(SYY.value));
		SMM.value = Math.floor(Math.abs(SMM.value));
		SDD.value = Math.floor(Math.abs(SDD.value));
	}
}

// -->

