也談農曆置閏

在看王曉華所著《算法的樂趣》(王曉華著. 算法的樂趣[M]. 北京:人民郵電出版社, 2015.04.)第11章中給出的農曆程序源代碼時,發如今農曆置閏方面彷佛有點問題,值得商榷。算法

書中給出的農曆閏月設置規則與《GB/T 33661-2017 農曆的編算和頒行》相一致,但長篇大論的比國標長多了,因此直接引用國標原文吧:數組

4 農曆的編排規則
4.1 以北京時間爲標準時間。
4.2 朔日爲農曆月的第一個農曆日。
4.3 包含節氣冬至在內的農曆月爲農曆十一月。
4.4 若從某個農曆十一月開始到下一個農曆十一月(不含)之間有13個農曆月,則須要置閏。置閏規則爲:取其中最早出現的一個不包含中氣的農曆月爲農曆閏月。
4.5 農曆十一月以後第2個(不計閏月)農曆月爲農曆年的起始月。函數

書中判斷是否須要置閏的代碼是CChineseCalendar::CalcLeapChnMonth(),沒有該書或沒有該書源代碼的能夠看這裏,有相同的文字說明和源代碼:
https://blog.csdn.net/orbit/article/details/9337377.net

CalcLeapChnMonth函數代碼初看沒有問題,與國標中4.4相一致,但其實存在一個邏輯漏洞: 代碼中的m_NewMoonJD數組是從前一年的十一月(冬至月)開始的,所以代碼blog

if(int(m_NewMoonJD[13] + 0.5) <= int(m_SolarTermsJD[24] + 0.5)) //第13月的月末沒有超過冬至,說明今年須要閏一個月it

考慮了本年前11個月是否須要置閏,但漏掉了另一個考慮選項:本年的第12個月(m_NewMoonJD[14])是否須要置閏?引用

要判斷本年第12個月是否須要置閏(閏冬月),就須要從本年冬至月計算到下年冬至月,發現有13個月時再看本年第12個月是否無中氣。簡單一點說,其實就是在用書中的代碼計算髮現本年無閏月時,還要用相同的代碼再算一遍第二年的閏月看是否是本年的第十二個月。第二遍計算時m_NewMoonJD數組中存儲的是從本年冬至到下年冬至之間的朔時刻。而在用現有的代碼計算髮現本年須要置閏時,也要檢查一下去年的冬月是否已經閏過,若是閏過就別再閏了。程序

若是不作這樣的修正,在碰到2033年這樣須要閏冬月的年份就會出現錯誤。時間

相關文章
相關標籤/搜索