博大精深的农历算法PHP代码

function lunarcalendar ($month, $year) {
	global $lnlunarcalendar;
	/*Lunar calendar 博大精深的农历
	原始数据和算法思路来自 S&amp;S Lab <a href="http://www.focus-2000.com" target="_blank">http://www.focus-2000.com</a> 可惜网站好像关了
	*/
	//农历每月的天数。每个元素为一年。每个元素中的数据为:[0]是闰月在哪个月,0为无闰月;[1]到[13]是每年12或13个月的每月天数;[14]是当年的天干次序,[15]是当年的地支次序
	$everymonth=array( 0=>array(8,0,0,0,0,0,0,0,0,0,0,0,29,30,7,1), 
					   1=>array(0,29,30,29,29,30,29,30,29,30,30,30,29,0,8,2), 
					   2=>array(0,30,29,30,29,29,30,29,30,29,30,30,30,0,9,3), 
					   3=>array(5,29,30,29,30,29,29,30,29,29,30,30,29,30,10,4), 
					   4=>array(0,30,30,29,30,29,29,30,29,29,30,30,29,0,1,5), 
					   5=>array(0,30,30,29,30,30,29,29,30,29,30,29,30,0,2,6), 
					   6=>array(4,29,30,30,29,30,29,30,29,30,29,30,29,30,3,7), 
					   7=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,4,8), 
					   8=>array(0,30,29,29,30,30,29,30,29,30,30,29,30,0,5,9), 
					   9=>array(2,29,30,29,29,30,29,30,29,30,30,30,29,30,6,10), 
					   10=>array(0,29,30,29,29,30,29,30,29,30,30,30,29,0,7,11), 
					   11=>array(6,30,29,30,29,29,30,29,29,30,30,29,30,30,8,12), 
					   12=>array(0,30,29,30,29,29,30,29,29,30,30,29,30,0,9,1), 
					   13=>array(0,30,30,29,30,29,29,30,29,29,30,29,30,0,10,2), 
					   14=>array(5,30,30,29,30,29,30,29,30,29,30,29,29,30,1,3), 
					   15=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,2,4), 
					   16=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,3,5), 
					   17=>array(2,30,29,29,30,29,30,30,29,30,30,29,30,29,4,6), 
					   18=>array(0,30,29,29,30,29,30,29,30,30,29,30,30,0,5,7), 
					   19=>array(7,29,30,29,29,30,29,29,30,30,29,30,30,30,6,8), 
					   20=>array(0,29,30,29,29,30,29,29,30,30,29,30,30,0,7,9), 
					   21=>array(0,30,29,30,29,29,30,29,29,30,29,30,30,0,8,10), 
					   22=>array(5,30,29,30,30,29,29,30,29,29,30,29,30,30,9,11), 
					   23=>array(0,29,30,30,29,30,29,30,29,29,30,29,30,0,10,12), 
					   24=>array(0,29,30,30,29,30,30,29,30,29,30,29,29,0,1,1), 
					   25=>array(4,30,29,30,29,30,30,29,30,30,29,30,29,30,2,2), 
					   26=>array(0,29,29,30,29,30,29,30,30,29,30,30,29,0,3,3), 
					   27=>array(0,30,29,29,30,29,30,29,30,29,30,30,30,0,4,4), 
					   28=>array(2,29,30,29,29,30,29,29,30,29,30,30,30,30,5,5), 
					   29=>array(0,29,30,29,29,30,29,29,30,29,30,30,30,0,6,6), 
					   30=>array(6,29,30,30,29,29,30,29,29,30,29,30,30,29,7,7), 
					   31=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,8,8), 
					   32=>array(0,30,30,30,29,30,29,30,29,29,30,29,30,0,9,9), 
					   33=>array(5,29,30,30,29,30,30,29,30,29,30,29,29,30,10,10), 
					   34=>array(0,29,30,29,30,30,29,30,29,30,30,29,30,0,1,11), 
					   35=>array(0,29,29,30,29,30,29,30,30,29,30,30,29,0,2,12), 
					   36=>array(3,30,29,29,30,29,29,30,30,29,30,30,30,29,3,1), 
					   37=>array(0,30,29,29,30,29,29,30,29,30,30,30,29,0,4,2), 
					   38=>array(7,30,30,29,29,30,29,29,30,29,30,30,29,30,5,3), 
					   39=>array(0,30,30,29,29,30,29,29,30,29,30,29,30,0,6,4), 
					   40=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,7,5), 
					   41=>array(6,30,30,29,30,30,29,30,29,29,30,29,30,29,8,6), 
					   42=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,9,7), 
					   43=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,10,8), 
					   44=>array(4,30,29,30,29,30,29,30,29,30,30,29,30,30,1,9), 
					   45=>array(0,29,29,30,29,29,30,29,30,30,30,29,30,0,2,10), 
					   46=>array(0,30,29,29,30,29,29,30,29,30,30,29,30,0,3,11), 
					   47=>array(2,30,30,29,29,30,29,29,30,29,30,29,30,30,4,12), 
					   48=>array(0,30,29,30,29,30,29,29,30,29,30,29,30,0,5,1), 
					   49=>array(7,30,29,30,30,29,30,29,29,30,29,30,29,30,6,2), 
					   50=>array(0,29,30,30,29,30,30,29,29,30,29,30,29,0,7,3), 
					   51=>array(0,30,29,30,30,29,30,29,30,29,30,29,30,0,8,4), 
					   52=>array(5,29,30,29,30,29,30,29,30,30,29,30,29,30,9,5), 
					   53=>array(0,29,30,29,29,30,30,29,30,30,29,30,29,0,10,6), 
					   54=>array(0,30,29,30,29,29,30,29,30,30,29,30,30,0,1,7), 
					   55=>array(3,29,30,29,30,29,29,30,29,30,29,30,30,30,2,8), 
					   56=>array(0,29,30,29,30,29,29,30,29,30,29,30,30,0,3,9), 
					   57=>array(8,30,29,30,29,30,29,29,30,29,30,29,30,29,4,10), 
					   58=>array(0,30,30,30,29,30,29,29,30,29,30,29,30,0,5,11), 
					   59=>array(0,29,30,30,29,30,29,30,29,30,29,30,29,0,6,12), 
					   60=>array(6,30,29,30,29,30,30,29,30,29,30,29,30,29,7,1), 
					   61=>array(0,30,29,30,29,30,29,30,30,29,30,29,30,0,8,2), 
					   62=>array(0,29,30,29,29,30,29,30,30,29,30,30,29,0,9,3), 
					   63=>array(4,30,29,30,29,29,30,29,30,29,30,30,30,29,10,4), 
					   64=>array(0,30,29,30,29,29,30,29,30,29,30,30,30,0,1,5), 
					   65=>array(0,29,30,29,30,29,29,30,29,29,30,30,29,0,2,6), 
					   66=>array(3,30,30,30,29,30,29,29,30,29,29,30,30,29,3,7), 
					   67=>array(0,30,30,29,30,30,29,29,30,29,30,29,30,0,4,8), 
					   68=>array(7,29,30,29,30,30,29,30,29,30,29,30,29,30,5,9), 
					   69=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,6,10), 
					   70=>array(0,30,29,29,30,29,30,30,29,30,30,29,30,0,7,11), 
					   71=>array(5,29,30,29,29,30,29,30,29,30,30,30,29,30,8,12), 
					   72=>array(0,29,30,29,29,30,29,30,29,30,30,29,30,0,9,1), 
					   73=>array(0,30,29,30,29,29,30,29,29,30,30,29,30,0,10,2), 
					   74=>array(4,30,30,29,30,29,29,30,29,29,30,30,29,30,1,3), 
					   75=>array(0,30,30,29,30,29,29,30,29,29,30,29,30,0,2,4), 
					   76=>array(8,30,30,29,30,29,30,29,30,29,29,30,29,30,3,5), 
					   77=>array(0,30,29,30,30,29,30,29,30,29,30,29,29,0,4,6), 
					   78=>array(0,30,29,30,30,29,30,30,29,30,29,30,29,0,5,7), 
					   79=>array(6,30,29,29,30,29,30,30,29,30,30,29,30,29,6,8), 
					   80=>array(0,30,29,29,30,29,30,29,30,30,29,30,30,0,7,9), 
					   81=>array(0,29,30,29,29,30,29,29,30,30,29,30,30,0,8,10), 
					   82=>array(4,30,29,30,29,29,30,29,29,30,29,30,30,30,9,11), 
					   83=>array(0,30,29,30,29,29,30,29,29,30,29,30,30,0,10,12), 
					   84=>array(10,30,29,30,30,29,29,30,29,29,30,29,30,30,1,1), 
					   85=>array(0,29,30,30,29,30,29,30,29,29,30,29,30,0,2,2), 
					   86=>array(0,29,30,30,29,30,30,29,30,29,30,29,29,0,3,3), 
					   87=>array(6,30,29,30,29,30,30,29,30,30,29,30,29,29,4,4), 
					   88=>array(0,30,29,30,29,30,29,30,30,29,30,30,29,0,5,5), 
					   89=>array(0,30,29,29,30,29,29,30,30,29,30,30,30,0,6,6), 
					   90=>array(5,29,30,29,29,30,29,29,30,29,30,30,30,30,7,7), 
					   91=>array(0,29,30,29,29,30,29,29,30,29,30,30,30,0,8,8), 
					   92=>array(0,29,30,30,29,29,30,29,29,30,29,30,30,0,9,9), 
					   93=>array(3,29,30,30,29,30,29,30,29,29,30,29,30,29,10,10), 
					   94=>array(0,30,30,30,29,30,29,30,29,29,30,29,30,0,1,11), 
					   95=>array(8,29,30,30,29,30,29,30,30,29,29,30,29,30,2,12), 
					   96=>array(0,29,30,29,30,30,29,30,29,30,30,29,29,0,3,1), 
					   97=>array(0,30,29,30,29,30,29,30,30,29,30,30,29,0,4,2), 
					   98=>array(5,30,29,29,30,29,29,30,30,29,30,30,29,30,5,3), 
					   99=>array(0,30,29,29,30,29,29,30,29,30,30,30,29,0,6,4), 
					   100=>array(0,30,30,29,29,30,29,29,30,29,30,30,29,0,7,5), 
					   101=>array(4,30,30,29,30,29,30,29,29,30,29,30,29,30,8,6), 
					   102=>array(0,30,30,29,30,29,30,29,29,30,29,30,29,0,9,7), 
					   103=>array(0,30,30,29,30,30,29,30,29,29,30,29,30,0,10,8), 
					   104=>array(2,29,30,29,30,30,29,30,29,30,29,30,29,30,1,9), 
					   105=>array(0,29,30,29,30,29,30,30,29,30,29,30,29,0,2,10), 
					   106=>array(7,30,29,30,29,30,29,30,29,30,30,29,30,30,3,11), 
					   107=>array(0,29,29,30,29,29,30,29,30,30,30,29,30,0,4,12), 
					   108=>array(0,30,29,29,30,29,29,30,29,30,30,29,30,0,5,1), 
					   109=>array(5,30,30,29,29,30,29,29,30,29,30,29,30,30,6,2), 
					   110=>array(0,30,29,30,29,30,29,29,30,29,30,29,30,0,7,3), 
					   111=>array(0,30,29,30,30,29,30,29,29,30,29,30,29,0,8,4), 
					   112=>array(4,30,29,30,30,29,30,29,30,29,30,29,30,29,9,5), 
					   113=>array(0,30,29,30,29,30,30,29,30,29,30,29,30,0,10,6), 
					   114=>array(9,29,30,29,30,29,30,29,30,30,29,30,29,30,1,7), 
					   115=>array(0,29,30,29,29,30,29,30,30,30,29,30,29,0,2,8), 
					   116=>array(0,30,29,30,29,29,30,29,30,30,29,30,30,0,3,9), 
					   117=>array(6,29,30,29,30,29,29,30,29,30,29,30,30,30,4,10), 
					   118=>array(0,29,30,29,30,29,29,30,29,30,29,30,30,0,5,11), 
					   119=>array(0,30,29,30,29,30,29,29,30,29,29,30,30,0,6,12), 
					   120=>array(4,29,30,30,30,29,30,29,29,30,29,30,29,30,7,1) );
	//农历天干
	$mten=$lnlunarcalendar['tiangan'];
	//农历地支
	$mtwelve=$lnlunarcalendar['dizhi'];
	//农历月份
	$mmonth=$lnlunarcalendar['month'];
	//农历日
	$mday=$lnlunarcalendar['day'];
	//阳历总天数 至1900年12月21日
	$total=69*365+17+11; //1970年1月1日前的就不算了
	if ($year=="" || $month=="" || ($year<1970 or $year>2020)) return ''; //超出这个范围不计算
	//计算到所求日期阳历的总天数-自1900年12月21日始
	//先算年的和
	for ($y=1970; $y<$year;$y++){
		$total+=365;
		if ($y%4==0) $total ++;
	}
	//再加当年的几个月
	$total+=gmdate("z",gmmktime(0,0,0,$month,1,$year));
	//用农历的天数累加来判断是否超过阳历的天数
	$flag1=0; //判断跳出循环的条件
	$lcj=0;
	while ($lcj<=120){
		$lci=1;
		while ($lci<=13){
			$mtotal+=$everymonth[$lcj][$lci];
			if ($mtotal>=$total){
				$flag1=1;
				break;
			}
			$lci++;
		}
		if ($flag1==1) break;
			$lcj++;
	}
	//由上,得到的 $lci 为当前农历月, $lcj 为当前农历年
	//计算所求月份1号的农历日期
	$fisrtdaylunar=$everymonth[$lcj][$lci]-($mtotal-$total);
	$results['year']=$mten[$everymonth[$lcj][14]].$mtwelve[$everymonth[$lcj][15]]; //当前是什么年
	$daysthismonth=gmdate("t",gmmktime(0,0,0,$month,1,$year)); //当前月共几天
	$op=1;
	for ($i=1; $i<=$daysthismonth; $i++) {
		$possiblelunarday=$fisrtdaylunar+$op-1; //理论上叠加后的农历日
		if ($possiblelunarday<=$everymonth[$lcj][$lci]) { //在本月的天数范畴内
			$results[$i]=$mday[$possiblelunarday];
			$op+=1;
		}else { //不在本月的天数范畴内
			$results[$i]=$mday[1]; //退回到1日
			$fisrtdaylunar=1;
			$op=2;
		$curmonthnum=($everymonth[$lcj][0]!=0) ? 13 : 12; //当年有几个月
		if ($lci+1>$curmonthnum) { //第13/14个月了,转到下一年
			$lci=1;
			$lcj=$lcj+1;
		//换年头了,把新一年的天干地支也写上
		$results['year'].='/'.$mten[$everymonth[$lcj][14]].$mtwelve[$everymonth[$lcj][15]];
		} else { //还在这年里
			$lci=$lci+1;
			$lcj=$lcj;
			}
		}
		if ($results[$i]==$mday[1]) { //每月的初一应该显示当月是什么月
			if ($everymonth[$lcj][0]!=0) { //有闰月的年
				$monthss=($lci>$everymonth[$lcj][0]) ? ($lci-1) : $lci; //闰月后的月数-1
				if ($lci==$everymonth[$lcj][0]+1) { //这个月正好是闰月
					$monthssshow=$mmonth[0].$mmonth[$monthss]; //前面加个闰字
					$runyue=1;
				}else {
					$monthssshow=$mmonth[$monthss];
				}
			} else {
				$monthss=$lci;
				$monthssshow=$mmonth[$monthss];
			}
			if ($monthss<=10 == $runyue!=1) $monthssshow.=$mmonth[13]; //只有1个字的月加上‘月’字
				$results[$i]=$monthssshow;
			}
		}
		return $results;
	}
	//忘了加上这个:
	//农历用字
	$lnlunarcalendar=array(
		'tiangan'=>array("未知","甲","乙","丙","丁","戊","己","庚","辛","壬","癸"),
		'dizhi'=>array("未知","子年(鼠)","丑年(牛)","寅年(虎)","卯年(兔)","辰年(龙)",
		"巳年(蛇)","午年(马)","未年(羊)","申年(猴)","酉年(鸡)","戌年(狗)","亥年(猪)"),
		'month'=>array("闰","正","二","三","四","五","六",
		"七","八","九","十","十一","十二","月"),
		'day'=>array("未知","初一","初二","初三","初四","初五","初六","初七","初八","初九","初十",
		"十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
		"廿一","廿二","廿三","廿四","廿五","廿六","廿七","廿八","廿九","三十")
	);
posted @ 2012-09-28 22:23  虚一而静  阅读(696)  评论(0编辑  收藏  举报