專欄:天文 × 程式設計
二十四節氣(節氣,Solar Terms)將一個回歸年劃分為二十四個等份,每一節氣相隔 15° 太陽黃經。本文將介紹如何利用 VSOP87 理論精確計算太陽黃經,進而求得每一個節氣的發生時刻。
1. 什麼是太陽黃經?
太陽黃經(Ecliptic Longitude) 是太陽在黃道上的角度位置,以春分點(0°)為起點,沿黃道量測一整圈共 360°。
二十四節氣正是依據太陽黃經的位置來定義。
每當太陽黃經到達 15° 的整數倍,便進入新的節氣。
例如:
- 春分:0°
- 清明:15°
- 穀雨:30°
- 立夏:45°
- …
- 冬至:270°
- …
- 雨水:330°
- 驚蟄:345°
因此,節氣的本質並不是依照日期,而是依照太陽在黃道上的實際位置。
2. VSOP87——行星軌道理論
VSOP87(Variations Séculaires des Orbites Planétaires) 是 Pierre Bretagnon 於 1987 年在法國巴黎經度局(Bureau des Longitudes)提出的行星運動理論。
它利用大量三角級數來描述各行星的運行軌道,其中地球模型包含超過兩千個級數項,因此能夠非常精確地推算太陽視位置。
基本形式如下:
L = L₀(τ)
+ L₁(τ) · τ
+ L₂(τ) · τ²
+ L₃(τ) · τ³
+ ...
其中:
- τ = (JDE − 2451545.0) / 365250
- JDE:Julian Ephemeris Day
- τ:自 J2000 起算的儒略千年數(Julian Millennia)
- 每一項 Lᵢ(τ) 皆由大量三角函數組成:
Lᵢ(τ) = Σ Aₖ · cos(Bₖ + Cₖ · τ)
VSOP87 在 西元前 4000 年至西元 8000 年期間,太陽位置的理論精度可達約:
±0.01 角秒(約 ±1 秒時間)
3. 求解節氣時刻——Newton–Raphson 法
節氣計算本質上是一個非線性方程求根問題。
已知目標黃經 λ₀(例如春分為 0°),需求得:
L = λ₀
其中:
- L:某時刻的太陽黃經。
- λ₀:目標節氣黃經。
Quizzman Calendar 採用 Newton–Raphson 方法反覆逼近。
function findSolarTerm(targetLon, yearJDE) {
let t = estimateInitial(targetLon, yearJDE);
for let i = 0; i < 50; i++ {
const L = sunLongitude;
const diff = normalizeAngle(L - targetLon);
if (Math.abs(diff) < 1e-8) break;
t -= diff / sunLongitudeRate;
}
return t;
}
由於 Newton–Raphson 屬於二次收斂(Quadratic Convergence)演算法,在初始值合理的情況下,通常只需 3~5 次迭代即可達到秒級精度。
4. 朔(New Moon)——Jean Meeus 演算法
朔(Shuò) 是指月球位於地球與太陽之間的時刻,也是農曆每個月的開始。
Quizzman Calendar 採用 Jean Meeus 在《Astronomical Algorithms》第 49 章提出的方法。
該演算法結合:
- 多項式近似
- 行星攝動修正
- 天文觀測資料
以計算每一次朔日的發生時刻。
在 1900–2100 年期間,其精度約可達:
±2 分鐘
5. 應用——判定閏月
農曆中的閏月(閏月),是指一個沒有包含中氣的農曆月份。
其中:
- 中氣:太陽黃經為 30° 的整數倍(0°、30°、60°……330°)。
演算法流程如下:
- 計算當年的所有朔日(通常為 12 或 13 次)。
- 計算全年十二個中氣。
- 找出沒有任何中氣落入的農曆月份。
- 該月份即為閏月。
- 若特殊情況出現多個候選月份,則依規則選擇冬至之後的第一個符合條件者。
正因如此,越南與中國的農曆有時會出現不同的閏月。
主要原因在於:
- 朔日的計算結果。
- 中氣發生時刻。
- 採用的時區不同。
當朔日或中氣恰好接近午夜時,不同時區可能導致日期不同,進而造成閏月判定出現差異。