219mze 发表于 2024-10-5 11:00:29

PHP实现阴历阳历的相互转换(支持1900~2100年)


    <div style="color: black; text-align: left; margin-bottom: 10px;">
      <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/1536594325866a340cdacf9~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1728305024&amp;x-signature=nv9UpFhqDHJuORHwbpAqo1J97HE%3D" style="width: 50%; margin-bottom: 20px;"></div>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">近期</span>做到一个项目, 需要阴历与阳历的相互转换, 网上找了<span style="color: black;">非常多</span>资料, <span style="color: black;">发掘</span><span style="color: black;">非常多</span>都是不准的, <span style="color: black;">然则</span>给了我参考价值</p>
      <h1 style="color: black; text-align: left; margin-bottom: 10px;">算法</h1>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">借用百度百科的 :</p>
      <h2 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">阳历</strong></h2>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">太阳历又<span style="color: black;">叫作</span>为阳历,是以地球绕太阳公转的运动周期为<span style="color: black;">基本</span>而制定的历法。</p>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">太阳历的历年近似等于回归年,一年12个月,这个“月”,<span style="color: black;">实质</span>上与朔望月无关。</p>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">阳历的月份、日期都与太阳在黄道上的位置较好地符合,<span style="color: black;">按照</span>阳历的日期,在一年中<span style="color: black;">能够</span><span style="color: black;">显著</span>看出四季寒暖变化的<span style="color: black;">状况</span>;但在<span style="color: black;">每一个</span>月份中,看不出月亮的朔、望、两弦。</p>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如今世界通行的公历<span style="color: black;">便是</span>一种阳历,平年365天,闰年366天,每四年一闰,每满百年少闰一次,到第四百年再闰,即每四百年中有97个闰年。公历的历年平均长度与回归年<span style="color: black;">仅有</span>26秒之差,要累积3300年才差一日。</p>
      <h2 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">阴历</strong></h2>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">希吉来历系太阴历,其计算<span style="color: black;">办法</span>是: 以太阴圆缺<span style="color: black;">1星期</span>为一月,历时29日12小时44分2.8秒,太阴圆缺十二周为一年,历时354日8小时48分33.6秒。<span style="color: black;">每年</span>的12个月中,6个单数月份(即1、3、5、7、9、11月)为“大建”,每月为30天; 6个双数月份(2、4、6、8、10、12月)为“小建”,每月为29天;在逢闰之年,将12月改大月为30天。该历以30年为<span style="color: black;">1星期</span>期,每<span style="color: black;">1星期</span>期里的第2、5、7、<span style="color: black;">十、</span>13、16、18、21、24、26、29年,共11年为闰年, 不设置闰月,而在12月末置一闰日,闰年为355日,另19年为平年,每年354日。故平均每年为354日8小时48分。按该历全年<span style="color: black;">实质</span>天数计算,比回归年约少10日21小时1分,积2.7回归年相差一月,积32.6回归年相差一年。该历对昼夜的计算,以日落为一天之始,到次日日落为一日,<span style="color: black;">一般</span><span style="color: black;">叫作</span>为夜行前,即黑夜在前,白昼在后,<span style="color: black;">形成</span>一天。希吉来历每年9月(莱麦丹)为伊斯兰教斋戒之月, 对这个月的起讫除了计算之外,还要由观察新月<span style="color: black;">是不是</span><span style="color: black;">显现</span>来决定。 即在8月29日这天进行观测,如见新月,第二日即为9月1日,黎明前<span style="color: black;">起始</span>斋戒,8月仍为小建; 如不见新月,第三日则为9月1日,8月即变为“大建”。到了9月29日傍晚,<span style="color: black;">亦</span>需要看月,如见新月,<span style="color: black;">次日</span><span style="color: black;">便是</span>10月1日,即为开斋节日,使9月变成“小建”;如未见新月,斋戒必须再延一天,9月即为“大建”。 12月(祖勒·希哲)上旬为朝觐日期,12月10日为宰牲节日。该历的星期,<span style="color: black;">运用</span>七曜(日、月、火、水、木、金、土)记日的周日法。每周逢金曜为“主麻日”,穆斯林在这一天举行“聚礼”。</p>
      <h3 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">思路</strong></h3>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">想要</span>计算给定的时间<span style="color: black;">针对</span>的农历是哪一天,<span style="color: black;">咱们</span>需要找一个参考时间,<span style="color: black;">而后</span>以该参考时间计算以后的时间。<span style="color: black;">首要</span>计算当前时间与参考时间相差的天数,<span style="color: black;">而后</span><span style="color: black;">经过</span>求出农历每年的天数,计算当前时间对应的是哪一年的第几天,最后计算出属于那个月的哪一个日期。</p>
      <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/15365943443538dc7e9398d~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1728305024&amp;x-signature=YGAX4ZO56%2BohxDcyDPB01Ib6PH0%3D" style="width: 50%; margin-bottom: 20px;"></div>
      <h3 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">计算生肖属相</strong></h3>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">日前</span>的做法是 阴历年份 - 1900 + 36 <span style="color: black;">而后</span>除以 12 取余数, 得出生肖属相的序号。</p>private function yearShengXiao($lunarYear)
      {
      // TODO 至于<span style="color: black;">为何</span><span style="color: black;">这般</span>弄, 我<span style="color: black;">亦</span>没搞清楚
      return self::SHENG_XIAO[($lunarYear - self::MIN_YEAR + 36) % 12]; // 年的属相
      }<h3 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">年的干支算法</strong></h3>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网上搜到的做法是用公元年来计算, <span style="color: black;">然则</span>不对, <span style="color: black;">而后</span>我换成阴历年居然就跟百度的日历能对上了, 这个我<span style="color: black;">亦</span>没弄清楚, <span style="color: black;">然则</span>能算出来了, 公式: 年数先减三,除10余数是天干,基数改用12除,余数便是地支年 (<span style="color: black;">倘若</span>余数为 0 ,则取最大序号)</p>private function yearGanZhi($lunarYear)
      {
      // 年数先减三,除10余数是天干,基数改用12除,余数便是地支年 (<span style="color: black;">倘若</span>余数为 0 ,则取最大序号)
      $yJiShu = $lunarYear - 3;
      $yTianGan = ($yJiShu % 10 == 0) ? 10 : $yJiShu % 10;
      $yDiZhi = ($yJiShu % 12 == 0) ? 10 : $yJiShu % 12;
      $yGanZhi = self::TIAN_GAN[$yTianGan - 1] . self::DI_ZHI[$yDiZhi - 1]; // // <span style="color: black;">因为</span>是从 0 <span style="color: black;">起始</span>,<span style="color: black;">这儿</span>再减一
      return $yGanZhi;
      }<h3 style="color: black; text-align: left; margin-bottom: 10px;"><strong style="color: blue;">月的干支算法</strong></h3>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网上搜索了, 没找到好的实现方式, 麻烦<span style="color: black;">晓得</span>的在<span style="color: black;">这儿</span>说一下,</p>
      <h3 style="color: black; text-align: left; margin-bottom: 10px;">日的干支算法</h3>
      <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网上搜到的:</p>G = 4C + + 5y + + + d - 3
      Z = 8C + + 5y + + + d + 7 + i
      其中C 是世纪数减一,y 是年份后两位,M 是月份,d 是日数。1月和2月按上一年的13月和14月来算。奇数月i=0,偶数月i=6。G 除以10的余数是天干,Z 除以12的余数是地支。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然则</span>不对, 麻烦有懂<span style="color: black;">亦</span><span style="color: black;">通知</span>下</p>
      <h1 style="color: black; text-align: left; margin-bottom: 10px;">PHP 的实现完整代码</h1>&lt;?php
      /**
      * 阳历和新历的转换
      */
      class SolarLunar {
      // 最小年
      const MIN_YEAR = 1900;
      // 最大年
      const MAX_YEAR = 2100;
      // <span style="color: black;">起始</span>的日期
      const START_DATE_STR = "1900-01-30";
      const CHINESE_NUMBER = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
      const CHINESE_NUMBER_SPECIAL = ["正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"];
      const TIAN_GAN = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
      const DI_ZHI = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
      const SHENG_XIAO = ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"];
      // 阴历年份的数据
      const LUNAR_INFO = [
      0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909
      0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919
      0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929
      0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939
      0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949
      0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959
      0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969
      0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979
      0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989
      0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,//1990-1999
      0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009
      0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019
      0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029
      0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039
      0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049
      0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50, 0x06b20,0x1a6c4,0x0aae0,//2050-2059
      0x0a2e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069
      0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079
      0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089
      0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099
      0x0d520];
      /**
      * 阴历转阳历
      * @param string $date
      * @param bool $leapMonthFlag
      * @return string
      */
      public function lunarToSolar($date = "", $leapMonthFlag = false) {
      try {
      $dateTime = new \DateTime($date);
      } catch (\Exception $exception) {
      return "";
      }
      $lunarYear = $dateTime-&gt;format("Y");
      $lunarMonth = $dateTime-&gt;format("n");
      $lunarDay = $dateTime-&gt;format("j");
      // <span style="color: black;">检测</span><span style="color: black;">是不是</span>合法
      if (!$this-&gt;checkLunarDate($lunarYear, $lunarMonth, $lunarDay, $leapMonthFlag)) {
      return "";
      }
      $offset = 0;
      for ($i = self::MIN_YEAR; $i &lt; $lunarYear; $i++) {
      $yearDaysCount = $this-&gt;getYearDays($i); // 求阴历某年天数
      $offset += $yearDaysCount;
      }
      //计算该年闰几月
      $leapMonth = $this-&gt;getLeapMonth($lunarYear);
      if ($leapMonthFlag &amp;&amp; $leapMonth != $lunarMonth) {
      // 您输入的闰月标志有误
      return "";
      }
      if ($leapMonth == 0 || ($lunarMonth &lt; $leapMonth) || ($lunarMonth == $leapMonth &amp;&amp; !$leapMonthFlag)) {
      for ($i = 1; $i &lt; $lunarMonth; $i++) {
      $tempMonthDaysCount = $this-&gt;getMonthDays($lunarYear, $i);
      $offset += $tempMonthDaysCount;
      }
      // <span style="color: black;">检测</span>日期<span style="color: black;">是不是</span>大于最大天
      if ($lunarDay &gt; $this-&gt;getMonthDays($lunarYear, $lunarMonth)) {
      // 不合法的农历日期
      return "";
      }
      $offset += intval($lunarDay); // 加上当月的天数
      } else { //当年有闰月,且月份晚于或等于闰月
      for ($i = 1; $i &lt; $lunarMonth; $i++) {
      $tempMonthDaysCount = $this-&gt;getMonthDays($lunarYear, $i);
      $offset += $tempMonthDaysCount;
      }
      if ($lunarMonth &gt; $leapMonth) {
      $temp = $this-&gt;getLeapMonthDays($lunarYear); // 计算闰月天数
      $offset += $temp; // 加上闰月天数
      if ($lunarDay &gt; $this-&gt;getMonthDays($lunarYear, $lunarMonth)) {
      // 不合法的农历日期
      return "";
      }
      $offset += intval($lunarDay);
      } else { // <span style="color: black;">倘若</span>需要计算的是闰月,则应<span style="color: black;">首要</span>加上与闰月对应的普通月的天数
      // 计算月为闰月
      $temp = $this-&gt;getMonthDays($lunarYear, $lunarMonth); // 计算非闰月天数
      $offset += $temp;
      if ($lunarDay &gt; $this-&gt;getLeapMonthDays($lunarYear)) {
      // 不合法的农历日期
      return "";
      }
      $offset += intval($lunarDay);
      }
      }
      try {
      $newDateTime = new \DateTime(self::START_DATE_STR);
      } catch (\Exception $exception) {
      return "";
      }
      $sumH = 24 * $offset;
      $newDateTime-&gt;add(new \DateInterval(PT . $sumH . H));
      return $newDateTime-&gt;format("Y-m-d");
      }
      /**
      * 把阳历转换为中文的阴历
      * @param string $date
      * @return string
      */
      public function solarToChineseLunar($date)
      {
      $dateTime = new \DateTime($date);
      list($lunarYear, $lunarMonth, $lunarDay, $leapMonth, $leapMonthFlag) = $this-&gt;calculateLunar($dateTime);
      $result = "";
      if($leapMonthFlag &amp;&amp; $lunarMonth == $leapMonth){
      $result .= "闰";
      }
      $solarYear = (int)$dateTime-&gt;format("Y");
      $solarMoth = (int)$dateTime-&gt;format("n");
      $solarDay = (int)$dateTime-&gt;format("j");
      $result .= self::CHINESE_NUMBER_SPECIAL[$lunarMonth-1] . "月";
      $result .= $this-&gt;chineseDayString($lunarDay) . "日";
      // 年的天干地支
      $yGanZhi = $this-&gt;yearGanZhi($lunarYear);
      // 生肖属相
      $yShengXiao = $this-&gt;yearShengXiao($lunarYear);
      $result .= "," . $yGanZhi . "年 [" . $yShengXiao . 年];
      // 月的天干地支
      $mTianGanDiZhi = $this-&gt;mothGanZhi($solarYear, $solarMoth, $solarDay);
      $result .= "," . $mTianGanDiZhi . 月;
      // 日的天干地支
      $dTianGanDiZhi = $this-&gt;dayGanZhi($solarYear, $solarMoth, $solarDay);
      $result .= "," . $dTianGanDiZhi . 日;
      return $result;
      }
      /**
      * 阳历转换为简单的中文阴历
      * @param string $date
      * @return string
      */
      public function solarToSimpleLunar($date)
      {
      $dateTime = new \DateTime($date);
      list($lunarYear, $lunarMonth, $lunarDay, $leapMonth, $leapMonthFlag) = $this-&gt;calculateLunar($dateTime);
      $result = $lunarYear . "年";
      if($leapMonthFlag &amp;&amp; $lunarMonth == $leapMonth) {
      $result .= "闰";
      }
      if($lunarMonth &lt; 10){
      $result .= "0" . $lunarMonth . "月";
      } else {
      $result .= $lunarMonth . "月";
      }
      if($lunarDay &lt; 10){
      $result .= "0" . $lunarDay . "日";
      } else {
      $result .= $lunarDay . "日";
      }
      return $result;
      }
      /**
      * 阳历转为正常的阴历
      * @param string $date
      * @param bool $isLeapMonth <span style="color: black;">是不是</span>是闰月
      * @return string
      */
      public function solarToLunar($date, &amp;$isLeapMonth = false)
      {
      $dateTime = new \DateTime($date);
      list($lunarYear, $lunarMonth, $lunarDay, $leapMonth, $leapMonthFlag) = $this-&gt;calculateLunar($dateTime);
      $result = $lunarYear . "-";
      if($lunarMonth &lt; 10){
      $result .= "0" . $lunarMonth . "-";
      } else {
      $result .= $lunarMonth . "-";
      }
      if($lunarDay &lt; 10){
      $result .= "0" . $lunarDay;
      } else {
      $result .= $lunarDay;
      }
      $isLeapMonth = false;
      if($leapMonthFlag &amp;&amp; $lunarMonth == $leapMonth) {
      $isLeapMonth = true;
      }
      return $result;
      }
      /**
      * 计算当前日期的阴历
      * @param \DateTime $dateTime
      * @return array
      */
      private function calculateLunar($dateTime)
      {
      $i = 0;
      $temp = 0;
      $leapMonthFlag = false;
      $isLeapYear = false;
      $startDate = new \DateTime(self::START_DATE_STR);
      $offset = $this-&gt;daysBwteen($dateTime, $startDate);
      for($i = self::MIN_YEAR; $i &lt; self::MAX_YEAR; $i++){
      $temp = $this-&gt;getYearDays($i); //求当年农历年天数
      if($offset - $temp &lt; 1){
      break;
      } else {
      $offset -= $temp;
      }
      }
      $lunarYear = $i;
      $leapMonth = $this-&gt;getLeapMonth($lunarYear); //计算该年闰哪个月
      //设定当年<span style="color: black;">是不是</span>有闰月
      if($leapMonth &gt; 0 ){
      $isLeapYear = true;
      } else {
      $isLeapYear = false;
      }
      for($i = 1; $i &lt;= 12; $i++){
      if($i == $leapMonth + 1 &amp;&amp; $isLeapYear){
      $temp = $this-&gt;getLeapMonthDays($lunarYear);
      $isLeapYear = false;
      $leapMonthFlag = true;
      $i--;
      } else {
      $temp = $this-&gt;getMonthDays($lunarYear, $i);
      }
      $offset -= $temp;
      if($offset &lt;= 0){
      break;
      }
      }
      $offset += $temp;
      $lunarMonth = $i;
      $lunarDay = $offset;
      return [$lunarYear, $lunarMonth, $lunarDay, $leapMonth, $leapMonthFlag];
      }
      /**
      * <span style="color: black;">检测</span>阴历<span style="color: black;">是不是</span>合法
      * @param int $lunarYear
      * @param int $lunarMonth
      * @param int $lunarDay
      * @param bool $leapMonthFlag
      * @return bool
      * @throws Exception
      */
      private function checkLunarDate($lunarYear, $lunarMonth, $lunarDay, $leapMonthFlag = false) {
      if ($lunarYear &lt; self::MIN_YEAR || $lunarYear &gt; self::MAX_YEAR) {
      // <span style="color: black;">违法</span>农历年份
      return false;
      }
      if ($lunarMonth &lt; 1 || $lunarMonth &gt; 12) {
      // <span style="color: black;">违法</span>农历月份
      return false;
      }
      if ($lunarDay &lt; 1 || $lunarDay &gt; 30) { // 中国的月最多30天
      // <span style="color: black;">违法</span>农历天数
      return false;
      }
      $leap = $this-&gt;getLeapMonth($lunarYear); // 计算该年应该闰哪个月
      if ($leapMonthFlag == true &amp;&amp; $lunarMonth != $leap) {
      // <span style="color: black;">违法</span>闰月
      return false;
      }
      return true;
      }
      /**
      * 计算该月总天数
      * @param int $year
      * @param int $month
      * @return int
      */
      private function getMonthDays($year, $month) {
      if ($month &gt; 31 || $month &lt; 0) {
      // error month
      return 0;
      }
      // 0X0FFFF中间12位<span style="color: black;">表率</span>12个月,1为大月,0为小月
      $bit = 1 &lt;&lt; (16 - $month);
      if (((self::LUNAR_INFO[$year - 1900] &amp; 0x0FFFF) &amp; $bit) == 0) {
      return 29;
      }
      return 30;
      }
      /**
      * 计算阴历年的总天数
      * @param int $year
      * @return int
      */
      private function getYearDays($year) {
      $sum = 29 * 12;
      for ($i = 0x8000; $i &gt;= 0x8; $i &gt;&gt;= 1) {
      if ((self::LUNAR_INFO[$year - 1900] &amp; 0xfff0 &amp; $i) != 0) {
      $sum++;
      }
      }
      return $sum + $this-&gt;getLeapMonthDays($year);
      }
      /**
      * 计算阴历年闰月多少天
      * @param int $year
      * @return int
      */
      private function getLeapMonthDays($year) {
      if ($this-&gt;getLeapMonth($year) != 0) {
      if ((self::LUNAR_INFO[$year - 1900] &amp; 0xf0000) == 0) {
      return 29;
      }
      return 30;
      }
      return 0;
      }
      /**
      * 计算阴历年闰哪个月 1-12 , 没闰传回 0
      * @param int $year
      * @return int
      */
      private function getLeapMonth($year) {
      return (int)(self::LUNAR_INFO[$year - 1900] &amp; 0xf);
      }
      /**
      * 计算差的天数
      * @param \DateTime $date
      * @param \DateTime $startDate
      * @return int
      */
      private function daysBwteen($date, $startDate)
      {
      $subValue = floatval($date-&gt;getTimestamp() - $startDate-&gt;getTimestamp()) / 86400.0 + 0.5;
      return intval($subValue);
      }
      /**
      * 计算年天干地支
      * @param $lunarYear
      * @return string
      */
      private function yearGanZhi($lunarYear)
      {
      // 年数先减三,除10余数是天干,基数改用12除,余数便是地支年 (<span style="color: black;">倘若</span>余数为 0 ,则取最大序号)
      $yJiShu = $lunarYear - 3;
      $yTianGan = ($yJiShu % 10 == 0) ? 10 : $yJiShu % 10;
      $yDiZhi = ($yJiShu % 12 == 0) ? 10 : $yJiShu % 12;
      $yGanZhi = self::TIAN_GAN[$yTianGan - 1] . self::DI_ZHI[$yDiZhi - 1]; // // <span style="color: black;">因为</span>是从 0 <span style="color: black;">起始</span>,<span style="color: black;">这儿</span>再减一
      return $yGanZhi;
      }
      /**
      * 计算年的生肖属相
      * @param $lunarYear
      * @return mixed
      */
      private function yearShengXiao($lunarYear)
      {
      // TODO 至于<span style="color: black;">为何</span><span style="color: black;">这般</span>弄, 我<span style="color: black;">亦</span>没搞清楚
      return self::SHENG_XIAO[($lunarYear - self::MIN_YEAR + 36) % 12]; // 年的属相
      }
      // TODO 尚未实现
      /**
      * 计算日的天干地支
      * @param $solarYear
      * @param $solarMoth
      * @param $solarDay
      * @return string
      */
      private function dayGanZhi($solarYear, $solarMoth, $solarDay)
      {
      return "";
      }
      // TODO 尚未实现
      /**
      * 计算月的天干地支
      * @param $solarYear
      * @param $solarMoth
      * @param $solarDay
      * @return string
      */
      private function mothGanZhi($solarYear, $solarMoth, $solarDay)
      {
      return "";
      }
      /**
      * 把天转换为中文字符
      * @param int $day
      * @return mixed|string
      */
      private function chineseDayString($day)
      {
      $chineseTen = ["初", "十", "廿", "三"];
      $n = 0;
      if($day % 10 == 0){
      $n = 9;
      } else {
      $n = $day % 10 - 1;
      }
      if($day &gt; 30){
      return "";
      }
      if($day == 20){
      return "二十";
      } else if($day == 10){
      return "初十";
      } else {
      return $chineseTen[$day / 10] . self::CHINESE_NUMBER[$n];
      }
      }
      }
      $solarLunar = new SolarLunar();
      $solarDate = "2010-01-05";
      $new_date = $solarLunar-&gt;solarToChineseLunar($solarDate);
      var_dump($solarDate . " 转为阴历: " . $new_date);
      $new_date = $solarLunar-&gt;solarToSimpleLunar($solarDate);
      var_dump($solarDate . " 转为阴历, 中文: " . $new_date);
      $new_date = $solarLunar-&gt;solarToLunar($solarDate, $isLeapMonth);
      var_dump("<span style="color: black;">是不是</span>是闰月: " . ($isLeapMonth ? "是" : "否"));
      var_dump($solarDate . " 转为阴历: " . $new_date);
      $lunarDate = "2099-11-25";
      $new_date = $solarLunar-&gt;lunarToSolar($lunarDate, false);
      var_dump($lunarDate . " 转新历为: " . $new_date);<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">输出:</p>string(67) "2010-01-05 转为阴历: 冬月廿一日,己丑年 [牛年],月,日"
      string(50) "2010-01-05 转为阴历, 中文: 2009年11月21日"
      string(20) "<span style="color: black;">是不是</span>是闰月: 否"
      string(35) "2010-01-05 转为阴历: 2009-11-21"
      string(35) "2099-11-25 转新历为: 2100-01-05"<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>想要学习交流PHP的<span style="color: black;">伴侣</span>,<span style="color: black;">能够</span>关注<span style="color: black;">博主</span>,私信【学习交流】手机用户<span style="color: black;">能够</span>直接私信,电脑端尚未开放此功能,需要下载app,我<span style="color: black;">已然</span>设置了自动回复,<span style="color: black;">详细</span>后续会自动回复各位。</p>
      <div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/1536594304065bd8669080b~noop.image?_iz=58558&amp;from=article.pc_detail&amp;lk3s=953192f4&amp;x-expires=1728305024&amp;x-signature=9HdL4Qw0rkO0Hxdd6kA5VRkYKYw%3D" style="width: 50%; margin-bottom: 20px;"></div>
    </div>




4zhvml8 发表于 2024-11-5 05:21:06

谢谢、感谢、感恩、辛苦了、有你真好等。
页: [1]
查看完整版本: PHP实现阴历阳历的相互转换(支持1900~2100年)