← 研究笔记
技术研究 · 2026-04-22

真太阳时的隐藏一环:时差方程与八字时柱

很多排盘实现的真太阳时只做了经度校正,却漏掉时差方程(Equation of Time)。这全年 -14 到 +16 分钟的偏差,足以让以两小时为界的八字时柱错落一柱。本文拆解真太阳时的两步校正与常见工程坑。

很多八字排盘实现都会做「真太阳时」校正,但绝大多数只做了一半——把钟表上的法定时间换算成当地的经度时间,却漏掉了另一半:时差方程(Equation of Time)。这一漏掉的部分全年可达 -14 到 +16 分钟,对以两小时为一柱的时柱来说,足以让一个人的时柱错到隔壁去。本文拆解真太阳时的两步校正,以及为什么第二步最容易被忽略。

真太阳时到底是什么

钟表上的时间是「法定时间」:一个时区里所有人共用同一个标准子午线的时刻。但太阳并不认行政区划。要还原「太阳真正走到你头顶正上方那一刻」,需要在法定时间上做两步修正:

用一句公式概括:

真太阳时 = 法定时间 + 经度校正 + 时差方程

常见的错误是只做了前两项,把「地方平时」当成了「真太阳时」。

第一步:经度校正(相对好写)

地球自转每小时 15 度,换算下来每 1 度经度差对应 4 分钟。所以从标准子午线到实际出生地的时间修正是:

longitudeCorrection = (longitude - standardMeridian) × 4   # 分钟,每度 4 分钟

这里唯一的坑是 standardMeridian(标准子午线)怎么取。它应该由该地当年的标准时区偏移决定,而标准时区偏移必须剥离夏令时(DST)——夏令时只是把钟拨快了,并不改变太阳的位置。剥离逻辑通常是:

standardOffset  = secondsFromGMT(date) - dstOffset(date)
standardMeridian = standardOffset / 3600 × 15

只要 DST 剥离对了,这一步在跨半球、跨夏冬令的各种边界上都能稳定给出正确结果:

地点 / 时段是否处于夏令时剥离后标准子午线
悉尼(南半球夏)是(AEDT)150°E
悉尼(南半球冬)否(AEST)150°E
纽约(夏)是(EDT)75°W
伦敦(夏)是(BST)

注意到悉尼夏冬都收敛到 150°E,纽约夏令时下仍取 75°W,伦敦夏令时下仍取 0°——这正是 DST 被正确剥离的标志。经度校正这一步,数学上并不难,难点在于它给人一种「我已经做完真太阳时」的错觉。

第二步:被漏掉的时差方程

「平太阳」是一个假想的、匀速运行的太阳;而真实的太阳,由于地球轨道是椭圆(近日点跑得快、远日点跑得慢)加上黄赤交角的存在,并不匀速。真太阳与平太阳之间的时间差,就是时差方程

它是一个只跟「一年中的第几天」有关的周期量,全年在约 -14 到 +16 分钟之间起伏:

日期时差方程(EoT)
2 月 11 日前后约 -14.6 分钟
5 月中旬约 +3.8 分钟
7 月下旬约 -6.2 分钟
11 月初约 +16.4 分钟
12 月下旬约 -0.5 分钟

一个常用的近似公式(以 N 为一年中的第几天)是:

B   = 2π × (N - 81) / 365
EoT ≈ 9.87·sin(2B) - 7.53·cos(B) - 1.5·sin(B)   # 单位:分钟

这个近似对于命理排盘的精度需求已经足够。若追求天文级精度,可换用更高阶的展开式,但对本文讨论的量级没有实质影响。

为什么它对八字时柱是「硬伤」

八字的时柱以两小时为一界(子时、丑时……,现代常以 23:00 / 01:00 / 03:00…… 为界)。这意味着任何一个把出生时刻推近或推离整点边界的误差,都可能改变时柱的落点。

而时差方程的量级是 ±16 分钟——单独一项就足以跨界。举个不指向任何真实个人的例子:某人出生在午时前后、钟表时间落在 11:40 到 12:20 这个区间,如果排盘只做经度校正、忽略 EoT,那么在一年中 EoT 偏大的月份里,校正后的真太阳时可能从「午初」滑到「巳末」,或者反过来——时柱直接错一柱,后续所有以时柱为基础的推演随之改变。

研究定位

本文只讨论历法与天文时间的换算方法。八字属于传统术数文化,相关推演仅为文化研究,并非命运预测或任何医疗、婚姻、灾祸方面的建议。

三个容易踩的工程坑

1. 用「当前时间」还是「出生时间」算时区

一个常见写法是拿 now()(程序运行的当下)去查时区偏移,而不是拿出生日期去查。大多数时候这「碰巧」是对的,因为剥离 DST 之后标准子午线通常不随年份变化。但一旦某地的历史时区规则发生过变动,用当下时间就会算错。正确做法是永远拿出生日期去查询当年的时区与夏令时状态。

2. 历史夏令时边界

中国曾在 1986 至 1991 年实行过夏令时(每年 4 月至 9 月拨快一小时)。操作系统的时区数据库对这段历史的识别,在起止边界上未必与官方公告逐日吻合。对这一时段、且出生在 5 至 9 月的记录,稳妥做法是在界面上提示用户「此时段实施过夏令时,请确认输入的是钟表时间」,而不是默默按某一种解释处理。

3. 经度数据库不全会「静默出错」

如果排盘依赖一个内置的城市经度表,而这个表只覆盖了少数大城市,那么表外的地点往往会 fallback 成「不校正」。这种错误最危险的地方在于它不报错、不提示,用户完全无从察觉。要么把经度库做全(至少覆盖主要人口城市),要么允许直接输入经纬度,并对 fallback 的情况给出明确提示。

修正后的完整算法

把两步校正合起来,一个语言无关的实现骨架是这样的:

function trueSolarTimeOffset(longitude, timeZone, birthDate):
    tzOffset          = secondsFromGMT(timeZone, birthDate)
                        - dstOffset(timeZone, birthDate)     # 剥离夏令时
    standardMeridian  = tzOffset / 3600 × 15
    longitudeCorrection = (longitude - standardMeridian) × 4  # 每度 4 分钟
    return longitudeCorrection + equationOfTime(birthDate)

关键改动只有一处:函数签名必须带上出生日期这个参数——EoT 依赖它,历史时区查询也依赖它。这个改动会沿调用链一路传导,所有拿到出生时刻的地方都要把日期透传进来。看似只是加了一个参数,实则是把「真太阳时」从半成品补成了完整实现。

小结

真太阳时的两步校正里,经度校正直白、容易写对,反而成了误导——它让人以为工作已经完成。真正决定成败的是那条只有十几分钟、却足以跨越时柱边界的时差方程。对任何以「出生时刻」为根基的排盘系统而言,漏掉 EoT 不是精度问题,而是可能改变结论的结构性缺陷。

Amos · research.xishe.ai · 转载注明出处