// JavaScript Document/*
//********************************************************************
// 2000～2030の日本における、新月・上弦・満月・下弦の月日の表示プログラム
// Write by かわうそ＠暦 (Email: koyomi37@yahoo.co.jp)
//*********************************************************************
//外から呼び出す関数は以下の３つ
//
// a. SetMoonName(str1,str2,str3,str4)　名称と、表示・非表示の制御
// b. NowMonthMoon()　システムから得た年月の一月分のデータ(月,日,名称)セット
// c. MonthMoon(yy,mm) 指定年月(yy年mm月)の 　　〃　　　　　　　　〃
//    yy: 2000～2030
//
// a は戻り値無し。
// b,c はデータセットの数を返す。
// 　　セットしたデータは大域変数 MonthMdata[i][n] にある。
// 　　※参考　n:0=月, n:1=日, n:2=名称
//
//■使用例■
////今月の、新月と満月の日だけを表示する例 //
//  SetMoonName('新月','','満月','');
//  ne = NowMonthMoon();
//  for (n = 0; n < ne ; n++) {
//		document.writeln(MonthMata[n][2]
//            + ': ' + MonthMdata[n][0] + '月' + MonthMdata[n][1] + '日');
//  }
//
// ※備考　例の最初の SetMoonName()を実行しなければ、上弦、下弦も表示となる。
//********************************************************************

var mfname = new Array("新月","上弦","満月","下弦");
var MonthMdata = [[0,0,""],[0,0,""],[0,0,""],[0,0,""],[0,0,""],[0,0,""]];
var mfminyear = 2000,mfmaxyear = 2030;

// 新月・上弦・満月・下弦の名称変更等
// （名前を空白 '' にすると非表示となる）
function SetMoonName(s1,s2,s3,s4) {
	mfname[0] = s1;
	mfname[1] = s2;
	mfname[2] = s3;
	mfname[3] = s4;
}

// 「今月」一月分のMonthMdataをセットし、データセットの個数を返す。
function NowMonthMoon() {
	var now = new Date();

	return MonthMoon(now.getFullYear(),now.getMonth()+1);
}

// 指定された年月の一月分のMonthMdataをセットし、データセットの個数を返す。
function MonthMoon(yy,mn) {
	var Mdays = new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
	var count,ans = 0;
	var errflag = 0;

	if ((yy < mfminyear) || (yy > mfmaxyear)) { errflag += 1; }
	if ((mn < 1) || (mn > 12)) { errflag += 2; }
	if (errflag != 0) {
		alert('MonthMoon(' + yy + ',' + mn + ') の引数が異常（or範囲外）です。');
		return 0;	// 答え無し
	}

	for (var i = 0; i < MonthMdata.length ; i++) {
		MonthMdata[i][0] = 0;
		MonthMdata[i][1] = 0;
		MonthMdata[i][2] = "";
	}
	if (yy % 4 == 0) {Mdays[2] = 29;}
	for (var i = 1; i <= 12; i++) {Mdays[i] += Mdays[i-1];}
	count = mfdecode(yy);
	for (var i = 0; i < count ; i++) {
		if (mfday[i] <= 0) continue;
		if (mfname[i % 4].length < 1) continue;	// mfname[n] が空白なら処理しない
		if ((mfday[i] > Mdays[mn-1]) && (mfday[i] <= Mdays[mn])) {
			MonthMdata[ans][0] = mn;
			MonthMdata[ans][1] = mfday[i] - Mdays[mn-1];;
			MonthMdata[ans][2] = mfname[i % 4];
			ans++;
		}
	}
	return ans;
}

//********************************************************************
// 以下は外部から直接呼び出す必要のない、内部処理ルーチン
//********************************************************************
var nstr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 月朔望データ (2000-2030)
var mfday = new Array(56);

// 1  : Year - 2000
// 2-3: 朔の年通日（朔が無い場合は 0）
// 4,5,6 : 上弦、満月、下弦の直前の朔年通日からの経過日数
// 以後繰り返し。数値は全て、36進。
// 年初、年末で朔～下弦まで全てがそろわない場所は 0が入る。
var mf = new Array(
 "0077EL108FM1U7EM2O6EM3H7EM4A7FN546EM5X7FN6Q8GN7K7FM8D8GN978FMA1000",
 "1003AG0O8FM1I8FM2C7EM367DL3Z7EM4S7FN5M6EM6F7FN787FN827FM8V8GN9P8F0",
 "2000060D9GM178FM218FM2V7EL3O8EM4I7EM5B7EM656EM6Y7EN7R7FN8L7FN9E8GN",
 "3037FM0W8GN1Q8FM2K8FL3D8FM478EL517EL5U7EM6O6EM7H7EM8A7FN947FN9X700",
 "40008F0M7FM1F8GN298FM329GM3W8FM4Q8EL5J8FM6D7EM768EM807EM8T7FN9N7F0",
 "5000040A7FN147FN1X8GN2R7FM3K8GM4E8FM579FM618FM6V7EL7O8EM8I7EM9C6EMA5000",
 "6007EN0T7FN1N7FN2G7GN3A7FM438GM4X8FM5Q8FM6K8FL7D8FM878EM917EL9U700",
 "70003B0J7EM1D6EM267FN2Z7FN3T7FM4M7FN5F8GN698FM729GM7W8FM8Q8EL9K7EL",
 "8088EM127EM1W6EM2P7EM3I7FN4C7FM557FN5Y8GN6S7FM7L8GM8F8FM998FLA2000",
 "9004BI0Q8EM1K7EM2E6DL377EM407FN4U6EM5N7FN6G7GN7A7FM838GN8X8FM9Q900",
 "A000070F8FM198FM237EL2W8EM3Q7EM4J7EM5D6EM667FN6Z7FN7T7FM8M8GN9G7FM",
 "B048GM0Y8FM1S8FL2L8FM3F8EM497EL527EM5W6EM6P7EM7I7FN8C7FN957FN9Z000",
 "C0009G0N8GN1H8FM2A9GM348FM3Y8EL4S7EL5L7EM6F6DL787EM817FN8V6EN9O7F0",
 "D000050C7FM158GN1Z8FM2S8GM3M8FM4G8EL598FM637EL6W8EM7Q7EM8J7FN9D7EM",
 "E008GO0V7FN1O7GN2I7FM3B8GM458FM4Y8FM5S8FL6L8FM7F8EM897EM927EM9W700",
 "F0005D0K7FN1E7FN277FN317FM3U8GN4N8GN5H8FM6A9GM748FM7Y8EL8S7EL9L8E0",
 "G000020A7EM137FN1X7EN2Q7FN3K7FM4D7FN568GN608FM6T8GM7N8FM8H8EL9A8FMA4000",
 "H006CK0S7EM1L7EN2F7EM387FN426EM4V7FN5O8GN6I7FM7B8GM858FM8Y9GM9S800",
 "I000290H8EM1B7EL248EM2Y7EM3R7EN4L6EM5E7FN677FN717FM7U8GN8O7FM9H8GM",
 "J068FM108FL1U7EL2N8EM3H7EM4A7EM546EM5X7EM6Q7FN7K7FM8D7FN977FMA0000",
 "K003BH0P8FM1J8FL2C8FM368EL407EL4T7EM5N6EM6G7EM797FN836EM8W7FN9Q7F0",
 "L000060D8GN178FM208GM2U8FM3O8EL4H8FM5B7EL648EM6Y7EM7R7EN8L6EM9E7FN",
 "M037FM0W7GN1Q7FM2J8GM3D8FM468FM508FL5U7EL6N8EM7H7EM8A7EM946EM9X700",
 "N0007F0M7FN1F7FN297FM328GM3W8FM4P8FM5J8FL6C8FM768EL807EL8T7EM9N7E0",
 "O000040B7FN157EN1Y7FN2S7FM3L7FN4E8GN588FM619GM6V8FM7P8EL8I8FM9C8EMA6000",
 "P007EM0T7EN1N7EM2G7FN3A6FM437FN4W8GN5Q7FM6J8GM7D8FM869FM908FM9U800",
 "Q0003B0J7EL1C7EM267EM2Z7FN3T6EM4M7FN5F7FN697FM728GM7W8FM8P8FM9J8FM",
 "R088EL127EL1V8EM2P7EM3I7EM4C6EM557FN5Y7FN6S7FM7L7FN8E8GN988GMA2000",
 "S005CJ0R8FL1K8FM2E8EM387EL417EM4V6EM5O7EM6H7FN7B6FM847FN8X8GN9R800",
 "T000070F8FM189GM228FM2W8EL3P8FM4J7EM5D6DL667EM6Z7FN7T6EM8M7FN9F8GN",
 "U047GN0Y7FM1R8GM2L8FM3E9FM488FM527EL5V8EM6P7EM7I7EM8C6EM957FN9Z600");

function asc2n(str) {
	var i,ie,ne;
	var ans;

	ne = nstr.length;
	ans = 0;
	for (i = 1; i <= str.length ; i++) {
		ans *= ne;
		ans += nstr.indexOf(str.substr(i-1,1));
	}
	return ans;
}

function mfdecode(yy) {
	var count = 0;

	for (var i = 0; i < mf.length ; i++) {
		if ((asc2n(mf[i].substr(0,1)) + 2000) == yy) {
			for (var j = 1; j < mf[i].length ; j += 5) {
				mfday[count] = asc2n(mf[i].substr(j,2));
				for (var k = 1; k <= 3 ; k++) {
					mfday[count+k] = asc2n(mf[i].substr(j+k+1,1));
					mfday[count+k] = (mfday[count+k] == 0) ? 0 : mfday[count+k] + mfday[count];
				}
				count += 4;
			}
			return count;
		}
	}
	return 0;
}

