最近一个项目中遇到需要计算指定日期对应建星的问题,作为一个外行人,经过摸索,最终写出了计算建星的方法,在这里分享一下。
关于建星的相关知识请点此阅读。
这里需要使用到一个扩展包:
composer require overtrue/chinese-calendar -vvv
具体实现代码如下:
<?php
use Overtrue\ChineseCalendar\Calendar;
// 建星的计算跟地支有直接关联,假设指定日期的月地支为`午`,则从本月初一开始计算,第一个日地支为`午`的日期对应的建星为`建`.
// 找到这个关键日期之后,再根据一定规则,计算出指定日期对应的建星。
// 本例中公历2020年6月22日,对应农历为二零二零年五月初二,对应月地支为`午`,对应天地支为`申`,对应的建星为'满'
$calendar = new Calendar();
$date = $calendar->solar(2020, 6, 22);
$diZhiArray = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
$jianXingArray = ['建', '除', '满', '平', '定', '执', '破', '危', '成', '收', '开', '闭'];
// 获取月地支
$currentYueDiZhi = mb_substr($date['ganzhi_month'], 1, 1);
// 获取本月农历最后一天
$nongLiMonthLastDay = $date['lunar_month'] == 2
? ($date['is_leap'] ? 29 : 28)// 闰年的农历二月为29天
: 30;
// 当月第一天的农历信息
$firstDayOfMonth = $calendar->lunar($date['lunar_year'], $date['lunar_month'], 1);
// 当月第一天农历信息对应的地支
$dizhiOfFirstInMonth = mb_substr($firstDayOfMonth['ganzhi_day'], 1, 1);
// 当月第一天农历信息对应的地支的索引
$dizhiOfFirstInMonthIdx = array_search($dizhiOfFirstInMonth, $diZhiArray);
// 计算当月哪一天是建星
$targetIdx = 1;
for ($i = 1; $i <= $nongLiMonthLastDay; $i++) {
if ($diZhiArray[$dizhiOfFirstInMonthIdx] == $currentYueDiZhi && $targetIdx == 1) {
$targetIdx = $i;
break;
}
if ($i > 1) {
$dizhiOfFirstInMonthIdx++;
if ($dizhiOfFirstInMonthIdx > 11) {
$dizhiOfFirstInMonthIdx = 0;
}
}
}
// 当月的农历xx为建星,本例中该值为12,即农历五月十二
$firstJianXingDayOfMonth = $targetIdx - 1;
// 如果是建星当天,则直接返回结果
if ($date['lunar_day'] == $firstJianXingDayOfMonth) {
return '建';
}
// 计算出差值并通过差值找到目标天对应的建星索引
$minus = $date['lunar_day'] < $firstJianXingDayOfMonth
? $date['lunar_day'] - $firstJianXingDayOfMonth
: ($date['lunar_day'] - $firstJianXingDayOfMonth) % 12;
$idx = $date['lunar_day'] < $firstJianXingDayOfMonth
? 12 + $minus
: $minus--;
// 如果当天是节气,则沿用前一天的建星
if ($date['term']) {
$idx--;
}
return $jianXingArray[$idx];
代码中有相关注释,欢迎交流。