logo头像

博学广问,自律静思

PHP获取指定日期的农历和节日

今天是圣诞节,用了半天做了一个节日祝福语和节日主题,效果还不错。可以在洋节和中国节日(包括农历节日 春节、中秋节等等)当天更换王柏元的博客的节日主题,并在站点公告里送上节日祝福语。 下面是关键的PHP类:Lunar。其中的getFestival()函数可传入的实参是不定数目的,可以通过传入的公历年月日,不传入默认是当前的服务器时间,函数实现了判断指定日期是否是已经设定的节日:比如中秋节、春节,同时还输出节日祝福语或诗句,返回的形式是一个数组。其余几个函数实现了获取公历和农历之间的转换,农历还支持返回当前日期农历的天干地支纪年以及生肖。 PHP获取农历和节日 PHP获取农历和节日  

lunarInfo\[$year-$this->MIN_YEAR\]; if($year==$this->MIN_YEAR&&$month<=2&&$date<=9){ return array(1891,'正月','初一','辛卯',1,1,'兔'); } return $this->getLunarByBetween($year,$this->getDaysBetweenSolar($year,$month,$date,$yearData\[1\],$yearData\[2\])); } /\*\* \* 将阴历转换为阳历 \* @param year 阴历-年 \* @param month 阴历-月,闰月处理:例如如果当年闰五月,那么第二个五月就传六月,相当于阴历有13个月,只是有的时候第13个月的天数为0 \* @param date 阴历-日 */ function convertLunarToSolar($year,$month,$date){ $yearData = $this->lunarInfo\[$year-$this->MIN_YEAR\]; $between = $this->getDaysBetweenLunar($year,$month,$date); $res = mktime(0,0,0,$yearData\[1\],$yearData\[2\],$year); $res = date('Y-m-d',$res+$between\*24\*60*60); $day = split_date($res); $year = $day\[0\]; $month= $day\[1\]; $day = $day\[2\]; return array($year, $month, $day); } /\*\* \* 判断是否是闰年 \* @param year */ function isLeapYear($year){ return (($year%4==0 && $year%100 !=0) || ($year%400==0)); } /\*\* \* 获取干支纪年 \* @param year */ function getLunarYearName($year){ $sky = array('庚','辛','壬','癸','甲','乙','丙','丁','戊','己'); $earth = array('申','酉','戌','亥','子','丑','寅','卯','辰','巳','午','未'); $year = $year.''; return $sky\[$year{3}\].$earth\[$year%12\]; } /\*\* \* 根据阴历年获取生肖 \* @param year 阴历年 */ function getYearZodiac($year){ $zodiac = array('猴','鸡','狗','猪','鼠','牛','虎','兔','龙','蛇','马','羊'); return $zodiac\[$year%12\]; } /\*\* \* 获取阳历月份的天数 \* @param year 阳历-年 \* @param month 阳历-月 */ function getSolarMonthDays($year,$month){ $monthHash = array('1'=>31,'2'=>$this->isLeapYear($year)?29:28,'3'=>31,'4'=>30,'5'=>31,'6'=>30,'7'=>31,'8'=>31,'9'=>30,'10'=>31,'11'=>30,'12'=>31); return $monthHash\["$month"\]; } /\*\* \* 获取阴历月份的天数 \* @param year 阴历-年 \* @param month 阴历-月,从一月开始 */ function getLunarMonthDays($year,$month){ $monthData = $this->getLunarMonths($year); return $monthData\[$month-1\]; } /\*\* \* 获取阴历每月的天数的数组 \* @param year */ function getLunarMonths($year){ $yearData = $this->lunarInfo\[$year - $this->MIN_YEAR\]; $leapMonth = $yearData\[0\]; $bit = decbin($yearData\[3\]); for ($i = 0; $i < strlen($bit);$i ++) { $bitArray\[$i\] = substr($bit, $i, 1); } for($k=0,$klen=16-count($bitArray);$k<$klen;$k++){ array_unshift($bitArray, '0'); } $bitArray = array_slice($bitArray,0,($leapMonth==0?12:13)); for($i=0; $ilunarInfo\[$year-$this->MIN_YEAR\]; $monthArray = $this->getLunarYearMonths($year); $len = count($monthArray); return ($monthArray\[$len-1\]==0?$monthArray\[$len-2\]:$monthArray\[$len-1\]); } function getLunarYearMonths($year){ //debugger; $monthData = $this->getLunarMonths($year); $res=array(); $temp=0; $yearData = $this->lunarInfo\[$year-$this->MIN_YEAR\]; $len = ($yearData\[0\]==0?12:13); for($i=0;$i<$len;$i++){ $temp=0; for($j=0;$j<=$i;$j++){ $temp+=$monthData\[$j\]; } array_push($res, $temp); } return $res; } /\*\* \* 获取闰月 \* @param year 阴历年份 */ function getLeapMonth($year){ $yearData = $this->lunarInfo\[$year-$this->MIN_YEAR\]; return $yearData\[0\]; } /\*\* \* 计算阴历日期与正月初一相隔的天数 \* @param year \* @param month \* @param date */ function getDaysBetweenLunar($year,$month,$date){ $yearMonth = $this->getLunarMonths($year); $res=0; for($i=1;$i<$month;$i++){ $res +=$yearMonth\[$i-1\]; } $res+=$date-1; return $res; } /\*\* \* 计算2个阳历日期之间的天数 \* @param year 阳历年 \* @param cmonth \* @param cdate \* @param dmonth 阴历正月对应的阳历月份 \* @param ddate 阴历初一对应的阳历天数 */ function getDaysBetweenSolar($year,$cmonth,$cdate,$dmonth,$ddate){ $a = mktime(0,0,0,$cmonth,$cdate,$year); $b = mktime(0,0,0,$dmonth,$ddate,$year); return ceil(($a-$b)/24/3600); } /\*\* \* 根据距离正月初一的天数计算阴历日期 \* @param year 阳历年 \* @param between 天数 */ function getLunarByBetween($year,$between){ //debugger; $lunarArray = array(); $yearMonth=array(); $t=0; $e=0; $leapMonth=0; $m=''; if($between==0){ array_push($lunarArray, $year,'正月','初一'); $t = 1; $e = 1; }else{ $year = $between>0? $year : ($year-1); $yearMonth = $this->getLunarYearMonths($year); $leapMonth = $this->getLeapMonth($year); $between = $between>0?$between : ($this->getLunarYearDays($year)+$between); for($i=0;$i<13;$i++){ if($between==$yearMonth\[$i\]){ $t=$i+2; $e=1; break; }else if($between<$yearMonth\[$i\]){ $t=$i+1; $e=$between-(empty($yearMonth\[$i-1\])?0:$yearMonth\[$i-1\])+1; break; } } $m = ($leapMonth!=0&&$t==$leapMonth+1)?('闰'.$this->getCapitalNum($t- 1,true)):$this->getCapitalNum(($leapMonth!=0&&$leapMonth+1<$t?($t-1):$t),true); array_push($lunarArray,$year,$m,$this->getCapitalNum($e,false)); } array_push($lunarArray,$this->getLunarYearName($year));//天干地支 array_push($lunarArray,$t,$e); array_push($lunarArray,$this->getYearZodiac($year));//12生肖 array_push($lunarArray,$leapMonth);//闰几月 return $lunarArray; } /\*\* \* 获取数字的阴历叫法 \* @param num 数字 \* @param isMonth 是否是月份的数字 */ function getCapitalNum($num,$isMonth){ $isMonth = $isMonth || false; $dateHash=array('0'=>'','1'=>'一','2'=>'二','3'=>'三','4'=>'四','5'=>'五','6'=>'六','7'=>'七','8'=>'八','9'=>'九','10'=>'十 '); $monthHash=array('0'=>'','1'=>'正月','2'=>'二月','3'=>'三月','4'=>'四月','5'=>'五月','6'=>'六月','7'=>'七月','8'=>'八月','9'=>'九月','10'=>'十月','11'=>'冬月','12'=>'腊月'); $res=''; if($isMonth){ $res = $monthHash\[$num\]; }else{ if($num<=10){ $res = '初'.$dateHash\[$num\]; }else if($num>10&&$num<20){ $res = '十'.$dateHash\[$num-10\]; }else if($num==20){ $res = "二十"; }else if($num>20&&$num<30){ $res = "廿".$dateHash\[$num-20\]; }else if($num==30){ $res = "三十"; } } return $res; } function getFestival(){ $festivals=array( array( array( "date"=>"正月初一", "info"=>"春节", "wish"=>"春回大地风光好,福满人间喜事多。" ), array( "date"=>"正月初二", "info"=>"新春", "wish"=>"春回大地风光好,福满人间喜事多。" ), array( "date"=>"正月初三", "info"=>"新春", "wish"=>"春回大地风光好,福满人间喜事多。" ), array( "date"=>"正月十五", "info"=>"元宵节", "wish"=>"火树银花合,星桥铁锁开。" ), array( "date"=>"七月初七", "info"=>"七夕", "wish"=>"七夕今宵看碧霄,牵牛织女渡河桥。" ), array( "date"=>"八月十五", "info"=>"中秋", "wish"=>"但愿人长久,千里共婵娟!" ), array( "date"=>"腊月廿九", "info"=>"除夕", "wish"=>"爆竹声中一岁除,春风送暖入屠苏。" ), array( "date"=>"腊月三十", "info"=>"除夕", "wish"=>"爆竹声中一岁除,春风送暖入屠苏。" ) ), array( array( "date"=>"1/1", "info"=>"元旦" ), array( "date"=>"2/14", "info"=>"情人节" ), array( "date"=>"10/1", "info"=>"国庆节" ), array( "date"=>"12/25", "info"=>"圣诞节", "wish"=>"Merry Christmas!" ) ) ); $args = func\_get\_args(); $y=isset($args\[0\])? $args\[0\]:date("Y"); $m=isset($args\[1\])? $args\[1\]:date("m"); $d=isset($args\[2\])? $args\[2\]:date("d"); $result=array(); $result\["is"\]=false; $ldate=$this->convertSolarToLunar($y,$m,$d); $day=$m."/".$d; $lday=$ldate\[1\]."".$ldate\[2\]; for($i=0;$i
@极客人
极客人 commented at 2016-08-12

愿闻其详

@头大
头大 commented at 2016-08-11

农历1991年之前的转成公历数据不对。