VSOP87 演算法:以太陽黃經精確計算二十四節氣

專欄:天文 × 程式設計

二十四節氣(節氣,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°)。

演算法流程如下:

  1. 計算當年的所有朔日(通常為 12 或 13 次)。
  2. 計算全年十二個中氣。
  3. 找出沒有任何中氣落入的農曆月份。
  4. 該月份即為閏月。
  5. 若特殊情況出現多個候選月份,則依規則選擇冬至之後的第一個符合條件者。

正因如此,越南與中國的農曆有時會出現不同的閏月。

主要原因在於:

  • 朔日的計算結果。
  • 中氣發生時刻。
  • 採用的時區不同。

當朔日或中氣恰好接近午夜時,不同時區可能導致日期不同,進而造成閏月判定出現差異。