We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
业务需要 产品通过chatGpt 找了好几个包都不可用 安总overtrue的 https://github.com/overtrue/chinese-calendar 也有bug 相差一天,以及八字不准确
谷歌自行搜索 https://github.com/6tail/lunar-php https://github.com/6tail/tyme4php
发现此开源项目 遂测试了下,转换准确,八字准确 维护支持好几种开发语言 佩服 作者的精力,感谢开源
lunar是一个支持阳历、阴历、佛历和道历的日历工具库,它开源免费,有多种开发语言的版本,不依赖第三方,支持阳历、阴历、佛历、道历、儒略日的相互转换,还支持星座、干支、生肖、节气、节日、彭祖百忌、每日宜忌、吉神宜趋、凶煞宜忌、吉神方位、冲煞、纳音、星宿、八字、五行、十神、建除十二值星、青龙名堂等十二神、黄道日及吉凶等。仅供参考,切勿迷信。
支持的时间跨度约为0001年至9999年。
composer require 6tail/lunar-php
$solar = Solar::fromDate(new DateTime(Carbon::createFromTimestamp($timestamp))); $lunar = $solar->getLunar(); // 阴历 一九九一年七月廿七壬戌 $lunarStr = $lunar->toString() . $lunar->getTimeGan() . $lunar->getTimeZhi(); // 获取八字,返回4个元素的数组,分别对应[年柱, 月柱, 日柱, 时柱] $bazi= $lunar->getBaZi();
作者还有另外一个项目 https://6tail.cn/tyme.html
阳历,就是“太阳历”,是依据太阳的变化(严格来说,应该是地球围绕太阳运动时,人在地球上所观测到的太阳的变化)来修订的历法,以地球绕太阳一圈的时间为一年。
小时候老师教过:“一三五七八十腊,三十一天永不差”。
阳历有很强的规律性,每年12个月,1、3、5、7、8、10、12月都为31天,2月份平年28天,闰年29天,其余月份为30天。是否闰年也好算,能被100整除的年份中能被400整除的是闰年,不能被100整除的年份中能被4整除的是闰年。
阴历,也就是“月亮历”,是依据月亮的变化来修订的历法。月亮每经历一次从圆到缺的循环,就是一个月。我国古人常把月亮叫做“太阴”,所以也叫“阴历”。 农历又有夏历、阴历、旧历、华历、中历等称。因使用“夏正”,旧时多称为夏历,1970 年以后“夏历”改称为“农历”。农历属于阴阳合历,其年份分为平年和闰年。
阴历全年12个月的总天数是354.3672天,它同季节变化的周期——阳历1年365.2422天)相差约11天。阴历分大小月:大月30天、小月29天。由于这样算与阳历有差别,会不能正确反映季节,我国就创造了一种带有一定阳历成分的阴历———“阴阳合历”,也就是农历,又叫夏历(夏朝开始的)。
阴历同阳历一年相差11天。因此,农历每3年需要闰(增加)1个月,5年闰2个月,7年闰3个月,19年闰7个月,周而复始,有闰月的那一年就被称为闰年。这种设置闰月的方法叫“19年7闰法”。
因此,阴历平年12个月,闰年13个月。 我们要从观测阴历的天文台处得到阴历数据,网上大多是1900年到2100年的数据(根本不是万年历啊摔(/゚Д゚)/)
大多数阳历转阴历的算法都是基于历史数据和数学计算得出的,因此准确度较高。但仍需注意,由于历法的复杂性和历史变迁,可能会存在一定的误差。 阳历转阴历在很多场景中都有应用,比如农历生日、农历节日、农历婚礼等。此外,对于一些传统文化活动和习俗,也常常需要使用阴历日期。
/** * 通过公历初始化 * @param Solar $solar 公历 * @return Lunar */ public static function fromSolar($solar) { $ly = LunarYear::fromYear($solar->getYear()); $lunarYear = 0; $lunarMonth = 0; $lunarDay = 0; foreach ($ly->getMonths() as $m) { $days = $solar->subtract(Solar::fromJulianDay($m->getFirstJulianDay())); if ($days < $m->getDayCount()) { $lunarYear = $m->getYear(); $lunarMonth = $m->getMonth(); $lunarDay = $days + 1; break; } } return new Lunar($lunarYear, $lunarMonth, $lunarDay, $solar->getHour(), $solar->getMinute(), $solar->getSecond(), $solar, $ly); } fromYear方法等下说, 此方法得到农历年 对象 然后 计算拿到 农历年, 农历月数 ,天 数 然后 传入 Lunar 拿到 农历对象
// 此方法 得到天干 地支 ,然后去调用当前类 compute 计算 核心 function __construct($lunarYear) { $lunarYear = intval($lunarYear); $this->year = $lunarYear; $offset = $lunarYear - 4; $yearGanIndex = $offset % 10; $yearZhiIndex = $offset % 12; if ($yearGanIndex < 0) { $yearGanIndex += 10; } if ($yearZhiIndex < 0) { $yearZhiIndex += 12; } $this->ganIndex = $yearGanIndex; $this->zhiIndex = $yearZhiIndex; $this->compute(); }
private function compute() { // 节气 $jq = array(); // 合朔,即每月初一 $hs = array(); // 每月天数(长度15) $dayCounts = array(); $months = array(); $currentYear = $this->year; $jd = floor(($currentYear - 2000) * 365.2422 + 180); // 355是2000.12冬至,得到较靠近jd的冬至估计值 $w = floor(($jd - 355 + 183) / 365.2422) * 365.2422 + 355; if (ShouXingUtil::calcQi($w) > $jd) { $w -= 365.2422; } // 25个节气时刻(北京时间),从冬至开始到下一个冬至以后 for ($i = 0; $i < 26; $i++) { $jq[] = ShouXingUtil::calcQi($w + 15.2184 * $i); } // 从上年的大雪到下年的立春 for ($i = 0, $j = count(Lunar::$JIE_QI_IN_USE); $i < $j; $i++) { if ($i == 0) { $jd = ShouXingUtil::qiAccurate2($jq[0] - 15.2184); } else if ($i <= 26) { $jd = ShouXingUtil::qiAccurate2($jq[$i - 1]); } else { $jd = ShouXingUtil::qiAccurate2($jq[25] + 15.2184 * ($i - 26)); } $this->jieQiJulianDays[] = $jd + Solar::$J2000; } // 冬至前的初一,今年首朔的日月黄经差w $w = ShouXingUtil::calcShuo($jq[0]); if ($w > $jq[0]) { $w -= 29.53; } // 递推每月初一 for ($i = 0; $i < 16; $i++) { $hs[] = ShouXingUtil::calcShuo($w + 29.5306 * $i); } // 每月 for ($i = 0; $i < 15; $i++) { $dayCounts[] = intval($hs[$i + 1] - $hs[$i]); $months[] = $i; } $prevYear = $currentYear - 1; $leapIndex = 16; if (in_array($currentYear, self::$LEAP_11)) { $leapIndex = 13; } else if (in_array($currentYear, self::$LEAP_12)) { $leapIndex = 14; } else if ($hs[13] <= $jq[24]) { $i = 1; while ($hs[$i + 1] > $jq[2 * $i] && $i < 13) { $i++; } $leapIndex = $i; } for ($i = $leapIndex; $i < 15; $i++) { $months[$i] -= 1; } $fm = -1; $index = -1; $y = $prevYear; for ($i = 0; $i < 15; $i++) { $dm = $hs[$i] + Solar::$J2000; $v2 = $months[$i]; $mc = self::$YMC[$v2 % 12]; if (1724360 <= $dm && $dm < 1729794) { $mc = self::$YMC[($v2 + 1) % 12]; } else if (1807724 <= $dm && $dm < 1808699) { $mc = self::$YMC[($v2 + 1) % 12]; } else if ($dm == 1729794 || $dm == 1808699) { $mc = 12; } if ($fm == -1) { $fm = $mc; $index = $mc; } if ($mc < $fm) { $y += 1; $index = 1; } $fm = $mc; if ($i == $leapIndex) { $mc = -$mc; } else if ($dm == 1729794 || $dm == 1808699) { $mc = -11; } $this->months[] = new LunarMonth($y, $mc, $dayCounts[$i], $hs[$i] + Solar::$J2000, $index); $index++; } }
八字是由年柱、月柱、日柱、时柱组成,其计算方法如下:
干支纪年:中国传统的干支纪年以 60 年为一个周期,依次为甲子、乙丑、丙寅…… 癸亥。从公元 4 年开始,公元年数减 3 除以 60 的余数对应干支纪年的序号,由此可确定年柱的干支。 快速推算:对于熟悉干支顺序的人,也可通过记忆一些关键年份来快速推算。例如,1984 年是甲子年,那么 1985 年就是乙丑年,以此类推,每过一年干支向后推一位。
五虎遁年起月诀:月柱的地支是固定的,正月为寅,二月为卯,三月为辰…… 十二月为丑。而天干则需根据年干来推算,口诀为 “甲己之年丙作首,乙庚之年戊为头,丙辛必定寻庚起,丁壬壬位顺行流,戊癸何方发,甲寅之上好追求”。 举例说明:如在甲子年,根据 “甲己之年丙作首”,正月为丙寅月,二月为丁卯月,三月为戊辰月等;在乙庚年,正月为戊寅月,二月为己卯月等。
公式计算法:最精确的方法是通过公式计算,公式为:r = (s + 4C + [C/4] + 5y + [y/4] + [3 * (M + 1) / 5] + d - 3),其中 r 为日柱的干支序号,s 为公元年数减 1900 后的个位数,C 为公元年数减 1900 后的百位数,y 为公元年数减 1900 后的后两位数,M 为月份数,d 为日期数。 查万年历:最简便的方法是直接查阅万年历,在万年历中可以直接查到对应日期的日柱干支。
五鼠遁日起时诀:时柱的地支是固定的,23 点至 1 点为子时,1 点至 3 点为丑时……21 点至 23 点为亥时。天干则根据日干来推算,口诀为 “甲己还加甲,乙庚丙作初,丙辛从戊起,丁壬庚子居,戊癸何方发,壬子是真途”。 举例说明:如在甲日或己日,子时为甲子时,丑时为乙丑时等;在乙日或庚日,子时为丙子时,丑时为丁丑时等。
我们现在使用的公历是格里历,这个历法的前身是儒略历法。儒略历法是罗马共和国于公元前45年1月1日起执行的,目的是取代旧罗马历法。在儒略历法中,一年被划分为12个月,单数月份31天,双数月份除2月份外30天,2月份平年29天,闰年30天,因此全年天数平年365天,闰年366天,年平均长度为365.25天。
而在天文学中,地球环绕太阳转动一圈的时间才是真正意义上的一天,周期约是365.2422天。因此,使用儒略历法之后,每年多算了11分钟14秒。由于误差不太大,头几年没什么关系,但是,一年又一年,误差累积起来,儒略历法就与实际的太阳年不合拍了。
到了16世纪,这个偏差已经达到了10天。于是在1582年,当时的教皇于1582年2月24日以教皇训令颁布,将1582年10月5日至14日抹掉,于是这10天就消失了,一去不复返。1582年10月4日过完了,第二天已经是10月15日了,于是历法又回到与太阳年同步。这便是今天世界上通用的历法——格里高利历,简称格里历,也就是我们说的公历。
我们都以为闰年规则为:四年一闰,百年不闰,四百年再闰。
殊不知这个规则是格里历的规则,也就是1582年开始执行的。
而在这之前,采用的是儒略历,简单粗暴,每4年一闰,所以,100年是闰年。
古时候的历法感觉比较混乱,查 寿星天文历 可以看到,阴历23年存在2个十二月的情况,阴历24年又闰五月。
为了兼容阴历和阳历的互转,我刻意的将23年第1个十二月,改为了闰十一月(即闰冬月)。
除此之外,查 寿星天文历 可以看到,农历237年没有三月的特殊情况。我想静静。
https://6tail.cn/calendar/demo.year.html 年份
https://6tail.cn/calendar/api.html#demo.bazi.html 八字排盘
https://6tail.cn/calendar/api.html#demo.bazi-solar.html 八字转阳历
https://blog.est.im/202009/stdout-008
The text was updated successfully, but these errors were encountered:
No branches or pull requests
业务需要
产品通过chatGpt 找了好几个包都不可用
安总overtrue的
https://github.com/overtrue/chinese-calendar
也有bug 相差一天,以及八字不准确
谷歌自行搜索
https://github.com/6tail/lunar-php
https://github.com/6tail/tyme4php
发现此开源项目 遂测试了下,转换准确,八字准确 维护支持好几种开发语言
佩服 作者的精力,感谢开源
lunar
lunar是一个支持阳历、阴历、佛历和道历的日历工具库,它开源免费,有多种开发语言的版本,不依赖第三方,支持阳历、阴历、佛历、道历、儒略日的相互转换,还支持星座、干支、生肖、节气、节日、彭祖百忌、每日宜忌、吉神宜趋、凶煞宜忌、吉神方位、冲煞、纳音、星宿、八字、五行、十神、建除十二值星、青龙名堂等十二神、黄道日及吉凶等。仅供参考,切勿迷信。
支持的时间跨度约为0001年至9999年。
使用
作者还有另外一个项目
https://6tail.cn/tyme.html
阳历转阴历 计算方式
阳历
阳历,就是“太阳历”,是依据太阳的变化(严格来说,应该是地球围绕太阳运动时,人在地球上所观测到的太阳的变化)来修订的历法,以地球绕太阳一圈的时间为一年。
小时候老师教过:“一三五七八十腊,三十一天永不差”。
阳历有很强的规律性,每年12个月,1、3、5、7、8、10、12月都为31天,2月份平年28天,闰年29天,其余月份为30天。是否闰年也好算,能被100整除的年份中能被400整除的是闰年,不能被100整除的年份中能被4整除的是闰年。
阴历
阴历,也就是“月亮历”,是依据月亮的变化来修订的历法。月亮每经历一次从圆到缺的循环,就是一个月。我国古人常把月亮叫做“太阴”,所以也叫“阴历”。
农历又有夏历、阴历、旧历、华历、中历等称。因使用“夏正”,旧时多称为夏历,1970 年以后“夏历”改称为“农历”。农历属于阴阳合历,其年份分为平年和闰年。
阴历全年12个月的总天数是354.3672天,它同季节变化的周期——阳历1年365.2422天)相差约11天。阴历分大小月:大月30天、小月29天。由于这样算与阳历有差别,会不能正确反映季节,我国就创造了一种带有一定阳历成分的阴历———“阴阳合历”,也就是农历,又叫夏历(夏朝开始的)。
阴历同阳历一年相差11天。因此,农历每3年需要闰(增加)1个月,5年闰2个月,7年闰3个月,19年闰7个月,周而复始,有闰月的那一年就被称为闰年。这种设置闰月的方法叫“19年7闰法”。
因此,阴历平年12个月,闰年13个月。
我们要从观测阴历的天文台处得到阴历数据,网上大多是1900年到2100年的数据(根本不是万年历啊摔(/゚Д゚)/)
大多数阳历转阴历的算法都是基于历史数据和数学计算得出的,因此准确度较高。但仍需注意,由于历法的复杂性和历史变迁,可能会存在一定的误差。
阳历转阴历在很多场景中都有应用,比如农历生日、农历节日、农历婚礼等。此外,对于一些传统文化活动和习俗,也常常需要使用阴历日期。
源码核心 通过公历初始化
看看fromYear 方法 底层调用
核心 compute 方法
八字的计算方法
八字是由年柱、月柱、日柱、时柱组成,其计算方法如下:
年柱的计算
干支纪年:中国传统的干支纪年以 60 年为一个周期,依次为甲子、乙丑、丙寅…… 癸亥。从公元 4 年开始,公元年数减 3 除以 60 的余数对应干支纪年的序号,由此可确定年柱的干支。
快速推算:对于熟悉干支顺序的人,也可通过记忆一些关键年份来快速推算。例如,1984 年是甲子年,那么 1985 年就是乙丑年,以此类推,每过一年干支向后推一位。
月柱的计算
五虎遁年起月诀:月柱的地支是固定的,正月为寅,二月为卯,三月为辰…… 十二月为丑。而天干则需根据年干来推算,口诀为 “甲己之年丙作首,乙庚之年戊为头,丙辛必定寻庚起,丁壬壬位顺行流,戊癸何方发,甲寅之上好追求”。
举例说明:如在甲子年,根据 “甲己之年丙作首”,正月为丙寅月,二月为丁卯月,三月为戊辰月等;在乙庚年,正月为戊寅月,二月为己卯月等。
日柱的计算
公式计算法:最精确的方法是通过公式计算,公式为:r = (s + 4C + [C/4] + 5y + [y/4] + [3 * (M + 1) / 5] + d - 3),其中 r 为日柱的干支序号,s 为公元年数减 1900 后的个位数,C 为公元年数减 1900 后的百位数,y 为公元年数减 1900 后的后两位数,M 为月份数,d 为日期数。
查万年历:最简便的方法是直接查阅万年历,在万年历中可以直接查到对应日期的日柱干支。
时柱的计算
五鼠遁日起时诀:时柱的地支是固定的,23 点至 1 点为子时,1 点至 3 点为丑时……21 点至 23 点为亥时。天干则根据日干来推算,口诀为 “甲己还加甲,乙庚丙作初,丙辛从戊起,丁壬庚子居,戊癸何方发,壬子是真途”。
举例说明:如在甲日或己日,子时为甲子时,丑时为乙丑时等;在乙日或庚日,子时为丙子时,丑时为丁丑时等。
为什么1582年10月少了10天?
我们现在使用的公历是格里历,这个历法的前身是儒略历法。儒略历法是罗马共和国于公元前45年1月1日起执行的,目的是取代旧罗马历法。在儒略历法中,一年被划分为12个月,单数月份31天,双数月份除2月份外30天,2月份平年29天,闰年30天,因此全年天数平年365天,闰年366天,年平均长度为365.25天。
而在天文学中,地球环绕太阳转动一圈的时间才是真正意义上的一天,周期约是365.2422天。因此,使用儒略历法之后,每年多算了11分钟14秒。由于误差不太大,头几年没什么关系,但是,一年又一年,误差累积起来,儒略历法就与实际的太阳年不合拍了。
到了16世纪,这个偏差已经达到了10天。于是在1582年,当时的教皇于1582年2月24日以教皇训令颁布,将1582年10月5日至14日抹掉,于是这10天就消失了,一去不复返。1582年10月4日过完了,第二天已经是10月15日了,于是历法又回到与太阳年同步。这便是今天世界上通用的历法——格里高利历,简称格里历,也就是我们说的公历。
为什么100年是闰年?
我们都以为闰年规则为:四年一闰,百年不闰,四百年再闰。
殊不知这个规则是格里历的规则,也就是1582年开始执行的。
而在这之前,采用的是儒略历,简单粗暴,每4年一闰,所以,100年是闰年。
为什么存在连续两年都有闰月的情况?
古时候的历法感觉比较混乱,查 寿星天文历 可以看到,阴历23年存在2个十二月的情况,阴历24年又闰五月。
为了兼容阴历和阳历的互转,我刻意的将23年第1个十二月,改为了闰十一月(即闰冬月)。
除此之外,查 寿星天文历 可以看到,农历237年没有三月的特殊情况。我想静静。
相关链接
https://6tail.cn/calendar/demo.year.html 年份
https://6tail.cn/calendar/api.html#demo.bazi.html 八字排盘
https://6tail.cn/calendar/api.html#demo.bazi-solar.html 八字转阳历
https://blog.est.im/202009/stdout-008
The text was updated successfully, but these errors were encountered: