干支计算本质是模60循环,以1984年2月2日(甲子日)为基准,用DateTime计算日期差取模60得索引,再分别对10和12取模匹配天干地支;需注意时区设为Asia/Shanghai,并严格按立春划分农历年。

干支计算的数学本质是模60循环
天干地支组合共60种,每60年(或日)一循环。PHP7中不能直接调用系统干支库,必须手动实现农历年/日与干支的映射关系。关键不是查表,而是理解起始点:1984年2月2日(农历甲子年正月初一)对应干支 "甲子",这是现代公历-干支转换最常用的基准日。所有计算都基于该日推算天数差再取模60。
date() 无法直接获取干支,需自行计算年干支和日干支
PHP内置函数不支持干支,date() 返回的只是公历信息。年干支和日干支要分开算:年干支看农历年(通常以立春为界),日干支则严格按公历日期推算(因干支纪日自春秋以来从未间断)。实际项目中多数只需日干支(如八字排盘、黄历服务),年干支反而容易出错——因为没考虑立春分界。
- 日干支 =
(基准日序号 + 公历日期差) % 60,结果查干支表 - 年干支不能简单用
date('Y')模10/12,必须先判断该年立春后才切换(例如2025年1月1日仍属农历癸卯年) - 推荐优先实现日干支,它稳定、可验证(如已知2024年1月1日是
癸卯日,可反推验证算法)
用 DateTime 算天数差再取模60是最可靠方式
避免用时间戳直接相减(可能受时区/闰秒影响),应使用 DateTime 对象计算日期差。基准日设为 '1984-02-02'(甲子日),用 diff() 得到总天数,再模60即可定位干支索引。
$base = new DateTime('1984-02-02');
$target = new DateTime('2024-06-15');
$days = $base->diff($target)->days;
$stemBranchIndex = $days % 60;
$stems = ['甲','乙','丙','丁','戊','己','庚','辛','壬','癸'];
$branches = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
$gan = $stems[$stemBranchIndex % 10];
$zhi = $branches[$stemBranchIndex % 12];
echo $gan . $zhi; // 输出:甲辰
注意:$base->diff($target) 默认返回正数天数,但若 $target 在基准日前,需加判断并调整符号;另外 PHP7.1+ 的 DateTime::diff 返回 DateInterval,->days 是总天数(非仅日部分)。
时区和农历年切换是线上服务最容易崩的两个点
服务器时区设为 Asia/Shanghai 是硬性要求,否则 DateTime('1984-02-02') 可能解析成前一日;农历年切换更隐蔽——很多代码把“每年2月4日”当固定立春日,但立春时刻每年不同(如2025年立春是2月3日22:10),严格场景需查节气表或调用专业农历库(如 overtrue/laravel-chinese-calendar)。普通需求用2月4日近似即可,但金融、命理类系统必须精确。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











