我們知道,太陽系的三個天體(太陽、地球、月亮)的運行規(guī)律是我們制訂歷法的依據(jù)。地球自轉(zhuǎn)一圈是一日。
公歷主要是參照地球與太陽的關(guān)系;
太陽繞地球一圈是365 .2422 天,公歷歷法以此為基準,取整數(shù),365天,通過某一年二月閏一天的辦法來平衡。
陰歷主要是參照地球與月亮(月相)的關(guān)系;
根據(jù)月像定出月份,初一朔月、十五望月,循環(huán)交替,并由此可以掌握潮水起落規(guī)律(月球引力影響)。一個朔望月的長度是29 .53 天,12個朔望月合一年是354.36天。
中國使用的農(nóng)歷屬于陰陰合歷。月是參照地球與月亮的關(guān)系,年是參數(shù)地球與太陽的關(guān)系。12個朔望月與公歷年的差距通過閏月來調(diào)整。
不管是365 .2422還是354.36,都不是整數(shù),所以公歷和農(nóng)歷都有不同的置閏方法。需要注意的是,公歷說的閏年是在二月加一天,農(nóng)歷所說的閏月是在某一年增加一個月,即某農(nóng)歷年可能有13個月。
公歷的置閏方法是:0.2422*4比較接近一天,自然四年一閏比較合適,但會多出來哪么一點點,0.0312天,100年后,也就是閏了25次后,累積到多了0.78天,0.78+0.24,比較接近1天,所以接下來的這一次不閏,依次循環(huán):通俗點的語言來描述就是逢能被4整除但不能被100整除的年份是閏年,但能被400整除的也是閏年。
農(nóng)歷的置閏方法:由于1回歸年為12.368個朔望月,0.368=368/1000=46/125,即125個回歸年的話正好余出46個朔望月,所以在一百二十五年中應(yīng)設(shè)置四十六個閏年。但因為這樣設(shè)閏太過復雜,經(jīng)推算,7/19最接近0.368。故一般地,在19年里中設(shè)置7個閏月,有閏月的年份全年383天或384天。
為什么采取“十九年七閏”的方法呢?一個朔望月平均是29.5306日,一個回歸年有12.368個朔望月,0.368小數(shù)部分的漸進分數(shù)是1/2 、1/3 、3/8 、4/11 、7/19 、46/125,即每二年加一個閏月,或每三年加一個閏月,或每八年加三個閏月……經(jīng)過推算,十九年加七個閏月比較合適。因為十九個回歸年=6939.6018日,而十九個農(nóng)歷年(加七個閏月后)共有235個朔望月,等于6939.6910日,這樣二者就差不多了。
對于陰歷,無法反映一年四季的寒置變換,所以農(nóng)歷增加了24節(jié)氣來反應(yīng)地球與太陽的運行關(guān)系,如春分與秋分就是太陽直射點的位置變換的中間時點。
24節(jié)氣需要反映的是地球繞太陽一周,分成24等分。而我們的公歷是以一年為整體并通過置閏的方式來平衡的,如果找到某一年的24節(jié)氣的時間(具體到豪秒)為基準,并可按規(guī)律推算出此后公歷時間對應(yīng)的日期。
1 JS代碼
較核心的代碼(完整代碼附后):
var solarTerm2 =new Array("小寒","大寒", "立春","雨水","驚蟄","春分","清明","谷雨", "立夏","小滿","芒種","夏至","小暑","大暑", "立秋","處暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至") var sTermInfo2 =new Array(0,21208, //1900年的各個節(jié)氣到小寒的分鐘數(shù) 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個節(jié)氣為幾日(從0小寒起算) var offDate = new Date( ( 31556925974.7*(y-1900) // 31556925974.7是一年的豪秒數(shù) + sTermInfo2[n]*60000 ) // 1分鐘60000毫秒,sTermInfo記錄的是分鐘數(shù) + Da(1900,0,6,2,5) ) // 指定的時間距GMT1970年1月1日午夜的毫秒數(shù)。 // 1900年1月6號為小寒,小于此時間,則返回負數(shù) return()) //根據(jù)世界時從 Date 對象返回月中的一天 (1 ~ 31)。 }效果:
2 C++代碼
較核心的代碼(完整代碼附后):
因為JS與C++各自時間處理的函數(shù)庫不同,所以C++寫起來費勁。
string jieqi[] = {"小寒","大寒", "立春","雨水","驚蟄","春分","清明","谷雨", "立夏","小滿","芒種","夏至","小暑","大暑", "立秋","處暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至"}; int jieqiDiffMinu[] = {0,21208, // 1900年的各個節(jié)氣到小寒的分鐘數(shù) 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個節(jié)氣為幾日(從0小寒起算) double ms = 31556925974.7*(y-1900); // 31556925974.7是一年)的豪秒數(shù) double tp = jieqiDiffMinu[n]*60; // 1分鐘60000毫秒,sTermInfo記錄的是分鐘數(shù) 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; i<y; i++) { for(int k=1;k<=365;k++) ms-=24*3600000; if(isLeapYear(i)) ms-=24*3600000; //ms-=366*24*3600000; // integral constant overflow } double ds = ms/(24*3600000); int monDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(y)) monDays[1] = 29; for(int j=0;j<12;j++) if(ds>monDays[j]) ds-=monDays[j]; return(ds); //根據(jù)世界時從 Date 對象返回月中的一天 (1 ~ 31)。 }運行效果:
附html+JS代碼:
<html> <body onload = "initial();"> <FORM name="CLD2" id="CLD2"> <SELECT style="font-SIZE: 11pt" name="SY2" id="SY2"> <SCRIPT language=JavaScript> // 寫日期和年份選項 for(i=1900;i<2050;i++) document.write('<option>'+i) </SCRIPT> </SELECT> 年 <SELECT style="font-SIZE: 11pt" name="SM2" id="SM2"> <SCRIPT language=JavaScript> for(i=1;i<13;i++) document.write('<option>'+i) </SCRIPT> </SELECT>月 <button type="button" onClick="myFunc()">查詢</button> <br> 節(jié): <input type="text" name="jie" size="6" /> 日期:<input type="text" name="jieD" size="6" /> <br> 氣: <input type="text" name="qi" size="6" /> 日期:<input type="text" name="qiD" size="6" /> </FORM> <script type="text/javascript"> function initial() { var Today = new Date(); var tY = Today.getFullYear(); var tM = Today.getMonth(); CLD2.SY2.selectedIndex=tY-1900; CLD2.SM2.selectedIndex=tM; } var solarTerm2 =new Array("小寒","大寒", "立春","雨水","驚蟄","春分","清明","谷雨", "立夏","小滿","芒種","夏至","小暑","大暑", "立秋","處暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至") var sTermInfo2 =new Array(0,21208, //1900年的各個節(jié)氣到小寒的分鐘數(shù) 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個節(jié)氣為幾日(從0小寒起算) var offDate = new Date( ( 31556925974.7*(y-1900) // 31556925974.7是一年的豪秒數(shù) + sTermInfo2[n]*60000 ) // 1分鐘60000毫秒,sTermInfo記錄的是分鐘數(shù) + Da(1900,0,6,2,5) ) // 指定的時間距GMT1970年1月1日午夜的毫秒數(shù)。 // 1900年1月6號為小寒,小于此時間,則返回負數(shù) return()) //根據(jù)世界時從 Date 對象返回月中的一天 (1 ~ 31)。 } function myFunc(){ y = document.CLD2.SY2.selectedIndex+1900; m = document.CLD2.SM2.selectedIndex; d1 = sTerm2(y,m*2 ) d2 = sTerm2(y,m*2+1) document.CLD2.jie.value = solarTerm2[m*2] document.CLD2.jieD.value = d1 document.CLD2.qi.value = solarTerm2[m*2+1] document.CLD2.qiD.value = d2 } </script> </BODY> </HTML>附C++代碼:
#include <iostream> #include <string> using namespace std; string jieqi[] = {"小寒","大寒", "立春","雨水","驚蟄","春分","清明","谷雨", "立夏","小滿","芒種","夏至","小暑","大暑", "立秋","處暑","白露","秋分","寒露","霜降", "立冬","小雪","大雪","冬至"}; int jieqiDiffMinu[] = {0,21208, // 1900年的各個節(jié)氣到小寒的分鐘數(shù) 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個節(jié)氣為幾日(從0小寒起算) double ms = 31556925974.7*(y-1900); // 31556925974.7是一年)的豪秒數(shù) double tp = jieqiDiffMinu[n]*60; // 1分鐘60000毫秒,sTermInfo記錄的是分鐘數(shù) 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; i<y; i++) { for(int k=1;k<=365;k++) ms-=24*3600000; if(isLeapYear(i)) ms-=24*3600000; //ms-=366*24*3600000; // integral constant overflow } double ds = ms/(24*3600000); int monDays[] = {31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(y)) monDays[1] = 29; for(int j=0;j<12;j++) if(ds>monDays[j]) ds-=monDays[j]; return(ds); //根據(jù)世界時從 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的余數(shù)是8); 年支=2-3+12=11=戌(2018/12的余數(shù)是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年)的節(jié)氣和對應(yīng)日期(公歷):n", 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); int jie = sTerm(y,m*2); printf("%s:%d ",jieqi[m*2].c_str(),jie); int qi = sTerm(y,m*2+1); printf("%s:%dn",jieqi[m*2+1].c_str(),qi); } } int main() { jieqiYear(2019); jieqiYear(2020); system("pause"); return 0; }-End-
1.《%2d是什么意思?總結(jié)很全面速看!C++和JS代碼推算24節(jié)氣和干支年份》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識,僅代表作者本人觀點,與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《%2d是什么意思?總結(jié)很全面速看!C++和JS代碼推算24節(jié)氣和干支年份》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進行證實,對其原創(chuàng)性、真實性、完整性、及時性不作任何保證。
3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/gl/2195303.html