程序化的理解,只供自己看。
历法是对日进行管理的方法,常见的更大的管理单位是月和年。
农历的月采用朔望月,即从一次月亮完全无光到下一次完全无兴的那一天为一个月。天文上,这个时间为29.2到29.8天,所以按天管理时,可能有29天,也可能有30天。
农历要求初一为朔,所以一个只有29称月小,一个月有30天称月大。一个月的大小,取决于天文观测的结果,与规则无关。一般来说,月会大小相间,连续月大的机会略多,连续月小的机会略少。
排定月,需要输入一定朔的时间,可以有日,也可以没有日。因为朔的时间不会超过一天,所以,只要出现时间倒转,就是多用了一天。
农历的年采用平太阳年,以冬至这天为所在的月为基准,向后两个月为正月。正月的初一,为一年之始。通过输入24个节气所在时间,可以确认哪一个月为十一月。两个十一月之间,如果有十三个月,则有一个月为闰月。24节气中只有十二个偶数节气,又称中气,第一个没有分配到中气的月,则为闰月。
农历可以从一个历元开始。从历元开始算0天,根据输入,每个朔月可以分配29或30天,得到一个月的数组,每个元素是当月开始的天数。
defallocLunaArray(newMoonTimes):result=[0]last=newMoonTimes[0]foriinrange(1,len(newMoonTimes)):result.append(result[-1]+29iflast<newMoonTimeselse30)last=newMoonTimes[i]returnresult
同样,基于同一个历元,输入一个24节气的天数,可以分析到月的名称。以1到24代表各节气,中气为偶数,22为冬至。
LunaArray = [0, 29, 59, 88 ... ] days of curresponding month.
solarTerms = [ 6, 22, 38, 54, ... ] days of curresponding term, start with first solar term.
def allocLunaNameArray(lunaArray: int[], solarTerms: int[], firstSolarTerm: int):
m = 0
result = []
winter = 0, leap = -1
for solarTerm, days in enumrate(solarTerms)):
skip odd term.
if (solarTerms + firstSolarTerm) % 2 == 1:
continue
end at last month.
if m >= len(luaArray):
break;
leap month is first month skip even term.
if lunaArray[m + 1] < days:
if leap < 0:
leap = m
m += 1
if (solarTerms + firstSolarTerm) % 24 == 22:
result.append((winter, leap, m))
winter = m
return result