0

0

php计算农历的实例代码

小云云

小云云

发布时间:2018-03-08 09:08:45

|

2363人浏览过

|

来源于php中文网

原创

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]));
    }
    function convertSolarMonthToLunar($year,$month) {
        $yearData = $this->lunarInfo[$year-$this->MIN_YEAR];
        if($year==$this->MIN_YEAR&&$month<=2&&$date<=9){
            return array(1891,'正月','初一','辛卯',1,1,'兔');
        }
        $month_days_ary = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
        $dd = $month_days_ary[$month];
        if($this->isLeapYear($year) && $month == 2) $dd++;
        $lunar_ary = array();
        for ($i = 1; $i < $dd; $i++) {
            $array = $this->getLunarByBetween($year,$this->getDaysBetweenSolar($year, $month, $i, $yearData[1], $yearData[2]));
            $array[] = $year . '-' . $month . '-' . $i;
            $lunar_ary[$i] = $array;
        }
        return $lunar_ary;
    }
    /**
     * 判断是否是闰年
     * @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 阴历-月,闰月处理:例如如果当年闰五月,那么第二个五月就传六月,相当于阴历有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    = explode('-', $res);
        $year    = $day[0];
        $month= $day[1];
        $day    = $day[2];
        return array($year, $month, $day);
    }
    /**
     * 获取阳历月份的天数
     * @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);
            $my_year = $this->toYear($year);
            array_push($lunarArray,$my_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;
    }
    //转换成中文年份
    function toYear($year){
        $arr = array("零","一","二","三","四","五","六","七","八","九");
        $year_arr = str_split($year);
        $str = $arr[$year_arr[0]].$arr[$year_arr[1]].$arr[$year_arr[2]].$arr[$year_arr[3]];
        return $str;
    }
    
    //中文年份转换成数字
    function toNumber($str){
        $arr = array("零"=>'0',"一"=>'1',"二"=>'2',"三"=>'3',"四"=>'4',"五"=>'5',"六"=>'6',"七"=>'7',"八"=>'8',"九"=>'9');
        $year_arr =  preg_split('/(?'','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 test(){
//         $date = $this->convertSolarToLunar(2018,5,1); //公历转农历
//         var_dump($date);
          
// //         var_dump($this->toNumber($date[0]));exit;
//      var_dump(  count($this->getLunarMonths(2017)));exit;
// //         $date = $this->getYearZodiac(2014,2,12); //根据阴历年获取生肖
// //         var_dump($date);
// //         $date = $this->isLeapYear(2014,2,12); //判断闰年
// //         var_dump($date);
// //         //其它功能也是这种调用方法

// //         //如果是农历转公历,代码如下:
//         $date = $this->convertLunarToSolar(2017,15,16); //农历转公历
//         var_dump($date);
        
        
//     }
    
//     function check(){
//         $date = $this->convertLunarToSolar(2017,7,29); //农历转公历
//         var_dump($date);
//        $a= $this->lunarNextCycleYearForLeap(2017,7,29,1);//闰年
//        var_dump($a);

// //         $a= $this->lunarNextCycleYearForNormal(2017,2,29,9);//平年
// //                var_dump($a);
       
//        $date = $this->convertLunarToSolar(2025,7,29); //农历转公历
//        var_dump($date);
       
//     }
    
    /**
     * 计算农历按N个月重复是哪天,没有对应的天数继续按周期循环
     * e.g 农历2017年第10个月的5个月后是2018年第二个月
     *注意农历有闰月的年份会出现13个月 不能简单认为一年有12个月
     * 上述例子   传递 $year=2017,$month=10,$interval=5
     * 返回 array(3) { [0]=> int(2018) [1]=> int(9) [2]=> int(30) }  分别对应 年,月,日,月份如果包含闰月 同理顺延
     */
    function lunarNextCycleMonth($year,$month,$day,$interval=1){
        if($year>$this->MAX_YEAR){
            return false;//防止死循环;
        }
        for ($i=1;$i<=$interval;$i++){
            $month++;
            //计算此年最大月份,如果month比这个最大月份还大, 则轮为下年一月 ,即year+1,month=1
            $yearData = $this->lunarInfo[$year-$this->MIN_YEAR];
            $maxMonth = ($yearData[0]==0?12:13);
            if($month>$maxMonth){
                $year++;
                $month=1;
            }
        }
        
        $lunarMonthDays=$this->getLunarMonthDays($year,$month);
        //如果下个周期的月份没有对应的day,例如有些月份没有农历30号,则继续递归查找
        if($lunarMonthDays<$day){
           return  $this->lunarNextCycleMonth($year,$month,$day,$interval);
        }else{
           return array($year,$month,$day);
        }
       
    }
    
    /**
     * 闰月重复按N年专用
     * 计算农历按N年重复是哪天,没有对应的天数继续按周期循环,闰月一定是重复成闰月直到符合,例如农历2017年闰六月30号一定重复至有闰六月的年份并且含有30号
     * e.g 农历2017年第10个月的5个月后是2018年第二个月
     * 注意农历有闰月的年份会出现13个月 不能简单认为一年有12个月
     * 上述例子   传递 $year=2017,$month=10,$interval=5
     * 返回 array(3) { [0]=> int(2018) [1]=> int(9) [2]=> int(30) }  分别对应 年,月,日,月份如果包含闰月 同理顺延
     * 
     */
    function lunarNextCycleYearForLeap($year,$month,$day,$interval=1){
        if($year>$this->MAX_YEAR){
            return false;//防止死循环;
        }

        //首先判断要想的日期是否闰月的日期,leapMonth的下一个月是闰月,例如leapMonth=6 那么7就是闰六月,后面月份顺推一个月,leapMonth=0代表没闰月
        if($month==$this->getLeapMonth($year)+1){
            //闰月的日期
            while ($year<=$this->MAX_YEAR){
                $year=$year+$interval;
                //找到有相同闰月为止
                $yearData = $this->lunarInfo[$year-$this->MIN_YEAR];
                if($yearData[0]!=0){
                    if($yearData[0]+1==$month){//有相同闰月的年份
                        //查看这个年份的闰月是否符合day数也相同
                        $lunarMonthDays=$this->getLunarMonthDays($year,$month);
                        //如果下个周期的月份没有对应的day,例如有些月份没有农历30号,则继续递归查找
                        if($lunarMonthDays<$day){
                            return  $this->lunarNextCycleYearForLeap($year,$month,$day,$interval);
                        }else{
                            return array($year,$month,$day);
                        }
                    }
                }
              
            }
        }
        
        //2100年之后也找不到 返回没找到
        return false;
    }
    
    
    /**
     * 平月重复按N年专用
     * 计算农历按N年重复是哪天,没有对应的天数继续按周期循环,闰月一定是重复成闰月直到符合,例如农历2017年闰六月30号一定重复至有闰六月的年份并且含有30号
     * e.g 农历2017年第10个月的5个月后是2018年第二个月
     * 注意农历有闰月的年份会出现13个月 不能简单认为一年有12个月
     * 上述例子   传递 $year=2017,$month=10,$interval=5
     * 返回 array(3) { [0]=> int(2018) [1]=> int(9) [2]=> int(30) }  分别对应 年,月,日,月份如果包含闰月 同理顺延
     */
    function lunarNextCycleYearForNormal($year,$month,$day,$interval=1){
    
 
        //平月的日期
        //1.先找到对应是农历几月,由于有闰月的年份会从闰月开始后面的月份数+1,要取出剔除
        $leapMonth=$this->getLeapMonth($year);
        if($leapMonth>0){
            //此年有闰月
            if($month>$leapMonth){
                $month--;//有闰月并且月份在闰月之后的月份数要-1才是真正的农历月
            }
        }
       

        //2.下个周期年,同理看看是不是有闰月,从闰月开始后面的月份数+1才是平月真正的月份
        //此时month的值等于月份数,例如农历平7月,month=7
        $year=$year+$interval;//下个周期第几年
        $leapMonth=$this->getLeapMonth($year);
        if($leapMonth>0){
            //此年有闰月
            if($month>$leapMonth){
                $month++;//有闰月并且月份在闰月之后的月份数要+1才是真正的需要匹配的月份
            }
        }
        
        $lunarMonthDays=$this->getLunarMonthDays($year,$month);
        //如果下个周期的月份没有对应的day,例如有些月份没有农历30号,则继续递归查找
        if($lunarMonthDays<$day){
            return  $this->lunarNextCycleYearForNormal($year,$month,$day,$interval);
        }else{
            return array($year,$month,$day);
        }
         
    }
}

相关推荐:

计算农历的函数

PHP实现公历与农历间的互转换方法介绍

初阶PHP Apache MySQL网站设计
初阶PHP Apache MySQL网站设计

初阶PHP Apache MySQL网站设计来自作者多年学习、应用和讲授PHP的经验与体会,是专为学习PHP+MySQL数据库编程人员编与的入门教材。在最后二章设计了2个贴近实际应用的典型案例:留言本系统和论坛系统,每个案例先介绍开发思路、步骤,再给出全部源代码,使所学内容与实际应用紧密结合,特别是论坛系统将全书的案例串讲起来,力求使读者学到最贴近应用前沿的知识和技能。

下载

php下实现农历日历的代码_PHP教程

立即学习PHP免费学习笔记(深入)”;

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

26

2025.12.30

金山文档相关教程
金山文档相关教程

本专题整合了金山文档相关教程,阅读专题下面的文章了解更多详细操作。

28

2025.12.30

PS反选快捷键
PS反选快捷键

本专题整合了ps反选快捷键介绍,阅读下面的文章找到答案。

25

2025.12.30

表格中一行两行的方法
表格中一行两行的方法

本专题整合了表格中一行两行的相关教程,阅读专题下面的文章了解更多详细内容。

3

2025.12.30

cpu温度过高解决方法大全
cpu温度过高解决方法大全

本专题整合了cpu温度过高相关教程,阅读专题下面的文章了解更多详细内容。

5

2025.12.30

ASCII码介绍
ASCII码介绍

本专题整合了ASCII码相关内容,阅读专题下面的文章了解更多详细内容。

31

2025.12.30

GPS是什么
GPS是什么

本专题整合了GPS相关内容,阅读专题下面的文章了解更多详细内容。

3

2025.12.30

wifi拒绝接入
wifi拒绝接入

本专题整合了wifi拒绝接入相关教程,阅读下面的文章了解更多详细方法。

9

2025.12.30

丰网速运介绍
丰网速运介绍

本专题整合了丰网速运查询入口以及相关内容,阅读专题下面的文章了解更多内容。

3

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.1万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 6.9万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号