我们知道,太阳系的三个天体(太阳、地球、月亮)的运行规律是我们制订历法的依据。地球自转一圈是一日。
公历主要是参照地球与太阳的关系;
太阳绕地球一圈是365 .2422 天,公历历法以此为基准,取整数,365天,通过某一年二月闰一天的办法来平衡。
阴历主要是参照地球与月亮(月相)的关系;
根据月像定出月份,初一朔月、十五望月,循环交替,并由此可以掌握潮水起落规律(月球引力影响)。一个朔望月的长度是29 .53 天,12个朔望月合一年是354.36天。
中国使用的农历属于阴阴合历。月是参照地球与月亮的关系,年是参数地球与太阳的关系。12个朔望月与公历年的差距通过闰月来调整。
不管是365 .2422还是354.36,都不是整数,所以公历和农历都有不同的置闰方法。需要注意的是,公历说的闰年是在二月加一天,农历所说的闰月是在某一年增加一个月,即某农历年可能有13个月。
公历的置闰方法是:0.2422*4比较接近一天,自然四年一闰比较合适,但会多出来哪么一点点,0.0312天,100年后,也就是闰了25次后,累积到多了0.78天,0.78+0.24,比较接近1天,所以接下来的这一次不闰,依次循环:通俗点的语言来描述就是逢能被4整除但不能被100整除的年份是闰年,但能被400整除的也是闰年。
农历的置闰方法:由于1回归年为12.368个朔望月,0.368=368/1000=46/125,即125个回归年的话正好余出46个朔望月,所以在一百二十五年中应设置四十六个闰年。但因为这样设闰太过复杂,经推算,7/19最接近0.368。故一般地,在19年里中设置7个闰月,有闰月的年份全年383天或384天。
为什么采取“十九年七闰”的方法呢?一个朔望月平均是29.5306日,一个回归年有12.368个朔望月,0.368小数部分的渐进分数是1/2 、1/3 、3/8 、4/11 、7/19 、46/125,即每二年加一个闰月,或每三年加一个闰月,或每八年加三个闰月……经过推算,十九年加七个闰月比较合适。因为十九个回归年=6939.6018日,而十九个农历年(加七个闰月后)共有235个朔望月,等于6939.6910日,这样二者就差不多了。
对于阴历,无法反映一年四季的寒置变换,所以农历增加了24节气来反应地球与太阳的运行关系,如春分与秋分就是太阳直射点的位置变换的中间时点。
24节气需要反映的是地球绕太阳一周,分成24等分。而我们的公历是以一年为整体并通过置闰的方式来平衡的,如果找到某一年的24节气的时间(具体到豪秒)为基准,并可按规律推算出此后公历时间对应的日期。
1 JS代码
较核心的代码(完整代码附后):
var solarTerm2 =new Array("小寒","大寒", "立春","雨水","惊蛰","春分","清明","谷雨", "立夏","小满","芒种","夏至","小暑","大暑", "立秋","处暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至")var sTermInfo2 =new Array(0,21208, //1900年的各个节气到小寒的分钟数 42467,63836,85337,107014,128867,150921, 173149,195551,218072,240693,263343,285989, 308563,331033,353350,375494,397447,419210, 440795,462224,483532,504758)function sTerm2(y,n) {//===== 某年的第n个节气为几日(从0小寒起算) var offDate = new Date( ( 31556925974.7*(y-1900) // 31556925974.7是一年的豪秒数 + sTermInfo2[n]*60000 ) // 1分钟60000毫秒,sTermInfo记录的是分钟数+ Date.UTC(1900,0,6,2,5) ) // 指定的时间距GMT1970年1月1日午夜的毫秒数。 // 1900年1月6号为小寒,小于此时间,则返回负数 return(offDate.getUTCDate()) //根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。}
效果:
2 C++代码
较核心的代码(完整代码附后):
因为JS与C++各自时间处理的函数库不同,所以C++写起来费劲。
string jieqi[] = {"小寒","大寒", "立春","雨水","惊蛰","春分","清明","谷雨", "立夏","小满","芒种","夏至","小暑","大暑", "立秋","处暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至"};int jieqiDiffMinu[] = {0,21208,// 1900年的各个节气到小寒的分钟数 42467,63836,85337,107014,128867,150921, 173149,195551,218072,240693,263343,285989, 308563,331033,353350,375494,397447,419210, 440795,462224,483532,504758};bool isLeapYear(int y){return (y%4==0&&y%100!=0 || y%400==0);}int sTerm(int y,int n) {// 某年的第n个节气为几日(从0小寒起算)double ms = 31556925974.7*(y-1900); // 31556925974.7是一年(365.2422)的豪秒数double tp = jieqiDiffMinu[n]*60; // 1分钟60000毫秒,sTermInfo记录的是分钟数for(int ii=0;ii<3;ii++)// 处理溢出tp *=10;ms += tp;ms +=((6*24+2)*60+5)*60*1000; // 1900年1月6号2时5分为小寒for(int i=1900; imonDays[j])ds-=monDays[j];return(ds);//根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。}
运行效果:
附html+JS代码:
年 月 查询
节: 日期:
气: 日期:
附C++代码:
#include #include using namespace std;string jieqi[] = {"小寒","大寒", "立春","雨水","惊蛰","春分","清明","谷雨", "立夏","小满","芒种","夏至","小暑","大暑", "立秋","处暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至"};int jieqiDiffMinu[] = {0,21208,// 1900年的各个节气到小寒的分钟数 42467,63836,85337,107014,128867,150921, 173149,195551,218072,240693,263343,285989, 308563,331033,353350,375494,397447,419210, 440795,462224,483532,504758};bool isLeapYear(int y){return (y%4==0&&y%100!=0 || y%400==0);}int sTerm(int y,int n) {// 某年的第n个节气为几日(从0小寒起算)double ms = 31556925974.7*(y-1900); // 31556925974.7是一年(365.2422)的豪秒数double tp = jieqiDiffMinu[n]*60; // 1分钟60000毫秒,sTermInfo记录的是分钟数for(int ii=0;ii<3;ii++)// 处理溢出tp *=10;ms += tp;ms +=((6*24+2)*60+5)*60*1000; // 1900年1月6号2时5分为小寒for(int i=1900; imonDays[j])ds-=monDays[j];return(ds);//根据世界时从 Date 对象返回月中的一天 (1 ~ 31)。}string Gan[]={"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"};string Zhi[]={"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};string Shu[]={"鼠","牛","虎","免","龙","蛇","马","羊","猴","鸡","狗","猪"};/*10天干=(y%10)-3),如果小于0,再加10(y是年份);12地支=(y%12)-3),如果小于0,再加12;例:求公元2018年的干支?年干=8-3 =5 =戊(2018/10的余数是8);年支=2-3+12=11=戌(2018/12的余数是2);*/int gan(int y){int g = (y%10)-3;if(g<=0)g+=10;return g;}int zhi(int y){int z = (y%12)-3;if(z<=0)z+=12;return z;}void jieqiYear(int y){printf("%d(%s%s%s年)的节气和对应日期(公历):", y,Gan[gan(y)-1].c_str(),Zhi[zhi(y)-1].c_str(),Shu[zhi(y)-1].c_str());for(int m=0; m<12; m++){printf("%2d月: ",m+1);intjie = sTerm(y,m*2);printf("%s:%d ",jieqi[m*2].c_str(),jie);intqi = sTerm(y,m*2+1);printf("%s:%d",jieqi[m*2+1].c_str(),qi);}}int main(){jieqiYear(2019);jieqiYear(2020); system("pause");return 0;}
-End-