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. 若特殊情况出现多个候选月份,则依规则选择冬至之后的第一个符合条件者。

正因如此,越南与中国的农历有时会出现不同的闰月。

主要原因在于:

  • 朔日的计算结果。
  • 中气发生时刻。
  • 采用的时区不同。

当朔日或中气恰好接近午夜时,不同时区可能导致日期不同,进而造成闰月判定出现差异。