今天用php实现对农历(阴历/旧历)的增减计算,因为这个不是历法不是世界通用的,所以并不是像strtotime直接对时间戳增减的方式完成,
但是操作方式也类似,只不过绕多了一步。
首先介绍一个农历阳历操作工具Lunar.php:
lunar是一个无依赖的支持阳历和阴历的日历工具库,它开源免费,有javascript、java、c#、php、python、go、typescript版本,不依赖第三方,支持阳历阴历互转,它能用来制作日历,甚至算命。
目前支持公历和农历、星座、干支、生肖、节气、节日、彭祖百忌、每日宜忌、吉神宜趋、凶煞宜忌、吉神方位、冲煞、纳音、星宿、八字、五行、十神、建除十二值星、青龙名堂等十二神、黄道黑道日及吉凶等。
旧版本支持的时间跨度:1901-01-01(庚子年冬月十一)至2099-12-31(己未年冬月二十),v1.2.0及以上版本支持0001年至9999年。
github地址:github.com/6tail/lunar…
里面可以对阳历或者阴历增减x天,也就是next(x)函数,但是不太适用。基于这个类(Lunar这个工具可以很方便地将阴阳历互转)我写了一个简单的逻辑去对农历(阴历/旧历)+n年m月r日的对日期增减方式操作方式:
include ("Lunar.php");
use com\nlf\calendar\util\HolidayUtil;
use com\nlf\calendar\Lunar;
use com\nlf\calendar\Solar;
$solar = Solar::fromYmd(2021,04,28);
//根据阳历获取农历对象
$lunar = $solar->getLunar();
$ly = $lunar->getYear();
$lm = $lunar->getMonth();
$ld = $lunar->getDay();
//加1年对应的农历
$nextLunar = Lunar::fromYmd($ly + 1, $lm, $ld);
$nextLunarStr = $nextLunar->toString();
$nextSolar = $nextLunar->getSolar()->toString();
echo $nextLunarStr,'<br>';//二〇二二年三月十七
echo $nextSolar,'<br>';//2022-04-17
复制代码
原理很简单,就是对应的年月日增减即可,这样补充了next只能增减天数的不足。
这个很简单,当时想多了,想找个和strtotime(”+x year”,time());//这种一步到位的,后来想想上面自己这种先分开再处理的方式也可以,将上面的封装一下也可以一步到位。
但是,这个是有局限性的,比如不能日数加减不能超范围(超出本月),建议用next函数,月数加减不能超年限(本年),需要手动判断。
根据某些规律计算的年月日增减功能,和strtotime功能类型,只是没有写对时分秒的增减:
函数封装方式:
/**
* 阳历增减天数、月数、周数、年数
* @param $express string 表达式
* @param $lunarYmd string 阴历日期
* @return array
*/
function cal_lunar($express, $lunarYmd)
{
//拆分年月日时分秒
list($ly, $lm, $ld) = explode('-', date('Y-m-d', strtotime($lunarYmd)));
//移除两边空白字符串
$express = trim($express);
if (stripos($express, 'd') !== false) {
//取出符号,"+" 或者 "-"
$symbol = substr($express, 0, 1);
$num = intval(trim(str_replace(['day', 'days', 'd', '+', '-'], '', $express)));
$nextLunar = Lunar::fromYmd($ly, $lm, $ld);
$nextLunar = $symbol == '+' ? $nextLunar->next($num) : $nextLunar->next(-$num);
$lunar = $nextLunar->getYear() . '-' . $nextLunar->getMonth() . '-' . $nextLunar->getDay();
$nextLunarStr = $nextLunar->toString();
$nextSolar = $nextLunar->getSolar()->toString();
} elseif (stripos($express, 'w') !== false) {
//取出符号,"+" 或者 "-"
$symbol = substr($express, 0, 1);
$num = intval(trim(str_replace(['week', 'w', 'weeks', '+', '-'], '', $express)));
//转换为周的天数
$num = 7 * $num;
$nextLunar = Lunar::fromYmd($ly, $lm, $ld);
$nextLunar = $symbol == '+' ? $nextLunar->next($num) : $nextLunar->next(-$num);
$lunar = $nextLunar->getYear() . '-' . $nextLunar->getMonth() . '-' . $nextLunar->getDay();
$nextLunarStr = $nextLunar->toString();
$nextSolar = $nextLunar->getSolar()->toString();
} elseif (stripos($express, 'm') !== false) {
//取出符号,"+" 或者 "-"
$symbol = substr($express, 0, 1);
$num = intval(trim(str_replace(['month', 'months', 'm', '+', '-'], '', $express)));
if ($symbol == '+') {
$addNum = $lm + $num;
if ($addNum <= 12) {
$lm = $addNum;
} else {
$ly = $ly + intval($addNum / 12);
$lm = $addNum % 12;
}
} else {
if ($num < $lm) {
$lm = $lm - $num;
} else {
$lm = 12 - ($num - $lm) % 12;
$ly = $ly - intvaL(($num + $lm) / 12);
}
}
$nextLunar = Lunar::fromYmd($ly, $lm, $ld);
$nextLunarStr = $nextLunar->toString();
$lunar = $nextLunar->getYear() . '-' . $nextLunar->getMonth() . '-' . $nextLunar->getDay();
$nextSolar = $nextLunar->getSolar()->toString();
} elseif (stripos($express, 'y') !== false) {
//取出符号,"+" 或者 "-"
$symbol = substr($express, 0, 1);
$num = intval(trim(str_replace(['year', 'years', 'y', '+', '-'], '', $express)));
$nextLunar = Lunar::fromYmd($symbol == '+' ? $ly + $num : $ly - $num, $lm, $ld);
$nextLunarStr = $nextLunar->toString();
$lunar = $nextLunar->getYear() . '-' . $nextLunar->getMonth() . '-' . $nextLunar->getDay();
$nextSolar = $nextLunar->getSolar()->toString();
} else {
//直接转换返回
$nextLunar = Lunar::fromYmd($ly, $lm, $ld);
$nextLunarStr = $nextLunar->toString();
$lunar = $ly . '-' . $lm . '-' . $ld;
$nextSolar = $nextLunar->getSolar()->toString();
}
return [
'lunar' => $lunar,//阴历
'lunarStr' => $nextLunarStr,//阴历中文样式
'solar' => $nextSolar,//阳历
];
}
print_r(cal_lunar('-2 month',20210317));
Array
(
[lunar] => 2021-1-17
[lunarStr] => 二〇二一年正月十七
[solar] => 2021-02-28
)
复制代码
通过上面自己封装计算的农历增减函数,很方便地进行年月日的增减了,比如
cal_lunar(‘-2 month’,20210317);//当前农历减2个月
cal_lunar(‘-99 month’,20210317);//当前农历减99个月
cal_lunar(‘+5 month’,20210317);//当前农历增5个月
cal_lunar(‘+99 day’,20210317);//当前农历增99天
cal_lunar(‘-6 week’,20210317);//当前农历减6周
这个是自己根据lunar.php工具写的一个函数,自己测试没有问题哈,遇到问题记得留言哦。