# js-ephemeris-lite

[简体中文](./README.md) · [English](./README.en.md)

用于浏览器和 Node.js 的天文与中国历法库。提供天体位置、节气与月相、
农历与算术回历转换、干支和太阳时计算，采用纯 JavaScript 实现，附带 TypeScript 类型声明，
无运行时依赖。

行星模型以 VSOP2013 和 TOP2013 为理论来源，月球模型以 ELP/MPP02 为理论来源，
并按 DE441 校准。日月食采用本项目 C++ 版本的几何求解路线。古代历法资料、算术回历规则和部分中国年号记录来自
[《寿星天文历》](https://github.com/sxwnl/sxwnl)。同仓库的 `huangli-lite` 中，
节日资料亦来自该项目，神煞和每日宜忌主要参考
[cnlunar](https://github.com/OPN48/cnlunar)，并由本项目整理修改。完整来源、处理方式与许可见
[第三方声明](./THIRD_PARTY_NOTICES.zh-CN.md)。

个人主页：[redsc1.com](https://www.redsc1.com/)

在线工具箱：[redsc1.com/tools](https://www.redsc1.com/tools)——提供日历、气朔等浏览器工具。

## 安装

需要 Node.js 18 或更高版本；浏览器项目可通过支持 ES modules 的构建工具使用。

```sh
npm install js-ephemeris-lite
```

本文档对应当前 1.1.0 源码；使用已安装版本时，请以该版本随包文档为准。

### 只使用日月与历法

气朔、历法及太阳时入口已独立于其他行星模型。只需日月位置时，可使用：

```js
import { earthState, moonState } from 'js-ephemeris-lite/sun-moon';
```

原有主入口与 `/ephemeris` API 保持不变。内部按天体拆分系数，并让日月计算直接引用日月模型；支持 tree shaking 的打包器可去掉未使用的其他行星数据。直接使用浏览器 ESM 时，建议使用功能子入口，避免主入口静态加载全部模块。此改动减少的是按需加载／打包体积，不减少 npm 安装包中的总系数，也不改变精度档位或计算结果。

## 快速开始

将公历日期转换为农历，或生成一年的节气和月相表：

```js
import { solarToLunar, lunarToSolar, getQiShuoYear } from 'js-ephemeris-lite';

const options = { mode: 'china-astronomical', utcOffsetMinutes: 480 };

const lunar = solarToLunar({ year: 2025, month: 1, day: 29 }, options);
console.log(lunar.month, lunar.day); // 1 1

const solar = lunarToSolar({
  year: 2033, month: 11, day: 1, isLeap: true,
}, options);
console.log(solar);

const year = getQiShuoYear(2026, {
  ...options,
  lunarPhaseAnglesDeg: [0, 90, 180, 270],
});
console.log(year.events); // 节气、朔、上弦、望、下弦
```

需要单独求某次事件时，可用 `solveSolarLongitude(targetRadians, nearJdTT)`
或 `solveNewMoon(nearJdTT)`。完整示例见[历法与时间指南](./docs/time-and-calendar.md)。

## 按需求找示例

| 想做什么 | 主要 API | 示例与说明 |
| --- | --- | --- |
| 查询行星、日月的几何位置和速度 | `planetHeliocentricState()`、`planetGeocentricPosition()`、`moonGeocentricPosition()` | [天体位置](./docs/positions.md) |
| 读取 TSC1 星表并计算恒星位置 | `parseTsc1Catalog()`、`fixedStarPosition()` | [恒星表、API 与演示](./docs/fixed-stars.md) |
| 查询视黄经、赤经、赤纬和角速度 | `apparentBodyPosition()`、`apparentBodyState()` | [视位置](./docs/sky-events.md#视位置与恒星时) |
| 查询月相比例、照明、距日角和视直径 | `moonIllumination()`、`bodyPhenomena()` | [照明与视直径](./docs/sky-events.md#照明相位与视直径) |
| 查询地平坐标、天体出没与中天 | `bodyHorizontalPosition()`、`bodyRiseSetForDay()` | [地平位置与出没](./docs/sky-events.md#地平位置与天体出没) |
| 查询黄经穿越、合冲、留和入宫 | `searchLongitudeCrossings()`、`searchRelativeLongitude()`、`searchStations()`、`searchIngresses()` | [黄经事件](./docs/sky-events.md#黄经合冲留与入宫) |
| 查询近远点、交点、大距和赤经事件 | `searchLunarApsides()`、`searchLunarNodes()`、`searchGreatestElongations()` 等 | [轨道与赤经事件](./docs/sky-events.md#轨道与赤经事件) |
| 查询日出日落、太阳高度和晨昏蒙影 | `solarRiseSetForDate()`、`solarAltitude()` | [太阳观测](./docs/sky-events.md#日出日落与太阳高度) |
| 计算地方平太阳时、真太阳时与均时差 | `meanSolarTime()`、`trueSolarTime()`、`equationOfTime()` | [太阳时](./docs/time-and-calendar.md#地方平太阳时与真太阳时) |
| 搜索全球及地方日月食 | `searchSolarEclipses()`、`getLocalLunarEclipse()` 等 | [日月食查询](./docs/eclipse-search.md) |
| 查询节气、月相、农历和历史历法 | `getQiShuoYear()`、`solarToLunar()`、`calculateChineseCalendarYear()` | [时间与历法](./docs/time-and-calendar.md) |

所有专题示例都从包的公开入口导入，并注明输入时间尺度、角度和距离单位。

仓库内的恒星表示例可直接运行；第一个参数支持中文名、常用名、HIP/HR/HD、
Bayer 或 Flamsteed 编号，第二个参数是可选的 JD(TT)：

```sh
npm run demo:fixed-stars -- 角宿一 2460000.5
```

## 模型系数

行星系数集中在 [`src/planet-series.js`](./src/planet-series.js)，按水、金、地、火、木、土、天、海、冥排列；
月球单独在 [`src/moon-series.js`](./src/moon-series.js)，按 `L0/L1/…`、`B0/…`、`R0/…` 分阶。
月球使用全局分阶级数，三坐标共享相位多项式。公共参考系旋转在 [`src/planet-frame.js`](./src/planet-frame.js)。
基底和单位见文件头；完整说明见[架构](./docs/architecture.md#模型数据)。

## 功能

- 太阳、月球、八大行星及冥王星的位置与速度，提供日心、地心及地月质心接口。
- 完整 TSC1 v1 恒星表读取、别名查询、三维空间运动传播和恒星视位置；默认亮星数据由可选的 `star-catalog-lite` 提供。
- 九颗小行星及半人马小行星的长时间范围几何位置，由可选的 `asteroid-ephemeris-lite` 包提供。
- 二十四节气、七十二候、朔与指定月相求解。
- 阴阳历互转、闰月，以及中国历史历法和历史纪年查询。
- 年月日时干支、三种晚子时规则、地方平太阳时与真太阳时。
- 太阳高度、日出日落及极昼极夜判断。
- 面向应用的[日月食查询接口](./docs/eclipse-search.md)，接受常规日期和角度制
  观测位置，返回全球事件、接触时刻及地方可见性；不包含地图或行政区数据。

[视位置与天象搜索](./docs/sky-events.md)还提供三种参考面、
行星留与黄经穿越、月球照明、天体出没、近远点、交点、大距和赤经事件。
小行星可选包的安装方法、数据来源、误差范围和长年代说明见[小行星文档](./docs/asteroids.md)；
日月食接口的参数和时间约定见[日月食文档](./docs/eclipses.md)。

> **冥王星精度警告：推荐范围为 1600～2200 年。范围外仍可计算，但使用低精度后备模型，
> 位置、速度及天象时刻均不可视作高精度结果。**
> 计算对象是冥王星系统质心，不是本体中心或光心。
> 详见[精度说明](./docs/accuracy.md#冥王星)及 `PLUTO_MODEL_INFO`。

## 时间、单位与精度

- 位置和定气定朔求解使用 **JD(TT)**；历法、民用时间和地平观测使用 **JD(UT1)**。
  事件的 `time` 是不带时区的 `JulianTime`，用 `.toZonedTime(480)` 显示东八区时间。
  `solve…` 直接返回 `JulianTime`；数学层 `…TimeFast/Accurate` 仍返回 TT JD 数值。
- 几何位置采用 J2000 黄道坐标；行星距离为 AU，地心月球距离为 km。
  其他接口的单位见对应指南。
- 民用日期在 1582-10-15 起采用格里历，之前采用儒略历；天文年号 `0` 表示公元前 1 年。
- 主要星历模型面向天文年 `-6000..10000`，具体查询范围依 API 而异。
  精度随天体、年代和计算模式变化，求根容差不等于天文绝对精度。
- 时间层使用 `UTC ≈ UT1`，不包含闰秒或 EOP 数据；固定时区不自动处理夏令时。

定气定朔的 fast／mid／accurate **不只是保留项数不同**，而是三条不同成本的
事件求解路线：

| 档位 | 星历与物理链 | 求根方式 |
| --- | --- | --- |
| Fast | 事件专用 value-only 快速模型、简化光行时／光行差；最终主黄经使用完整级数 | 固定阶段快速修正，不接受自定义容差 |
| Mid（默认） | 定气定朔专用中等模型与解析角速度 | 按容差迭代，可选带区间保护的 solver |
| Accurate | 完整日月位置、参考系、章动、光行时、光行差及适用的引力偏折 | 在完整视位置上按容差迭代 |

因此它们的速度差不等于“少算了多少级数项”；一次求根会多次调用对应路线，
Accurate 的完整视位置状态还需要在相邻时刻重复计算位置。

定气定朔三档在 1900～2100 年每 5 年抽样（另含 2026 年，共 1008 个节气和 546 个朔），
相对 C++ DE441 参考链的实测结果如下。
参考链采用 Vondrák 2011 岁差、IAU 2000A 章动、光行时、周年光行差和多星体引力偏折；
速度数据来自同一台 Apple arm64 机器上的 Node.js 25.9.0 热路径，仅用于比较三个 JS 档位：

| Fast | Mid（默认） | Accurate |
| --- | --- | --- |
| **定气误差**：RMS 0.541 秒<br>最大 1.812 秒 | **定气误差**：RMS 0.205 秒<br>最大 0.627 秒 | **定气误差**：RMS 0.135 秒<br>最大 0.490 秒 |
| **定朔误差**：RMS 0.268 秒<br>最大 0.785 秒 | **定朔误差**：RMS 0.191 秒<br>最大 0.814 秒 | **定朔误差**：RMS 0.185 秒<br>最大 0.729 秒 |
| **定气速度**：8.14 µs | **定气速度**：24.69 µs | **定气速度**：129.01 µs |
| **定朔速度**：21.20 µs | **定朔速度**：53.61 µs | **定朔速度**：1105.44 µs |
| 大量排盘、快速预览 | 日历与 App 常规计算 | 高精度校验、研究用途 |

这里的“误差”是相对该参考链的时刻差，不是相对真实天象的统一误差上限；机器、运行时和
日期范围变化后速度与误差分布也会变化。Fast 采用固定阶段求根并在最终修正中使用完整
主黄经级数；结果支持目前的档位定位：Fast 优先速度，Mid
在成本与精度之间取平衡，Accurate 使用完整库内视位置模型。

适用范围、档位选择及限制见[精度说明](./docs/accuracy.md)。

几何位置函数直接接受 `'fast' | 'mid' | 'accurate'` 参数，视位置因另有多个选项而
使用 `{ accuracy }`；两者默认 `accurate`，三档共用一套离线排序的系数表。定朔定气也使用同名 `accuracy`，
但其档位还会切换事件专用模型和求根路线，因此速度倍率不与单次位置计算相同。

## 几何位置与全量理论对照

以下是 **1600～2200 年、同一组 2,050 个日期**相对 DE441 的三维几何位置 RMS，
单位 **km**，越小表示在这组样本上越接近 DE441。本库使用位置接口的 `accurate` 档；
全量理论不额外截断，不套用本库的 DE441 修正。

| 对象 | 本库 accurate | VSOP87A 全量 | VSOP2013 全量 | TOP2013 全量 |
| --- | ---: | ---: | ---: | ---: |
| 水星 | 6.05 | 14.8 | 5.71 | — |
| 金星 | 10.5 | 23.5 | 4.47 | — |
| 地月质心¹ | 14.8 | 46.6 | 3.04 | — |
| 火星 | 40.6 | 242 | 12.3 | — |
| 木星 | 80.7 | 1,100 | 32.6 | 32.8 |
| 土星 | 91.2 | 2,012 | 8.83 | 13.1 |
| 天王星 | 373 | 17,345 | 16,825 | 16,855 |
| 海王星 | 791 | 55,682 | 5,152 | 5,096 |

¹ 地球相关项统一比较**地月质心**：本库调用 `embPosition()`，VSOP87A 使用 `.emb` 表，
VSOP2013 使用第 3 体；不能把这一行当作物理地球中心误差。TOP2013 此处使用全量 L/B/R 表，
不提供内行星对照。

月球单列地心结果，同样为三维位置 RMS（km），每个区间各 2,050 个日期：

| 模型 | 1600～2200 | −1000～3000 | −6000～10000 |
| --- | ---: | ---: | ---: |
| 本库 accurate | 0.275 | 0.468 | 2.28 |
| ELP/MPP02 全量（DE405 参数） | 0.058 | 50.7 | 1,290 |
| ELP2000-82B 全量 | 9.49 | 666 | 5,327 |

本库包含 DE441 校准，原始理论的拟合基准与年代不同，因此这不是对各理论固有精度的排名，
也不是同项数或同速度比较。宽年代列包含原始理论的外推测试，不构成适用范围承诺。
这些是样本统计，不是全时段误差上限，也不能直接换算成节气、月相或其他事件的秒数。
[完整结果、三档比较、坐标转换与复现方法](./docs/model-comparison.md)。

## 相关包

各包可单独使用，八字、紫微和黄历包均依赖本天文核心。
定朔定气默认 `mid`；`solve…` 使用单次 `{ accuracy }`，中国历法及上层包使用各自的
`eventAccuracy` 实例／查询选项，不设置模块级全局状态。详见[档位说明](docs/time-and-calendar.md#定朔定气档位fast--mid--accurate)。

| 包 | 用途 |
| --- | --- |
| `js-ephemeris-lite` | 天文位置、事件、时间与中国历法 |
| [bazi-lite](https://github.com/RedSC1/js-ephemeris-lite/tree/main/packages/bazi) | 四柱、十神藏干、神煞、起运大运与反查 |
| [ziwei-lite](https://github.com/RedSC1/js-ephemeris-lite/tree/main/packages/ziwei) | 紫微命盘、流运、自定义规则与星曜反查 |
| [huangli-lite](https://github.com/RedSC1/js-ephemeris-lite/tree/main/packages/huangli) | 每日宜忌、神煞、节日、九宫飞星及简繁体展示 |

## 文档与许可

- [天体位置](./docs/positions.md)
- [时间、太阳时、干支与农历](./docs/time-and-calendar.md)
- [历史历法与纪年](./docs/calendar-history.md)
- [日出日落、视位置与事件搜索](./docs/sky-events.md)
- [日月食](./docs/eclipses.md)
- [精度与模型限制](./docs/accuracy.md)
- [架构](./docs/architecture.md)、[模型修正](./docs/model-corrections.md)、[开发与测试](./docs/development.md)
- [npm 自动发布流程](./docs/releases.md)

代码采用 [MPL-2.0](./LICENSE)。科学模型与历史数据的来源、许可和适用范围见
[中文第三方声明](./THIRD_PARTY_NOTICES.zh-CN.md)及
[英文第三方声明](./THIRD_PARTY_NOTICES.md)。

## 常见问题与设计说明（FAQ）

**Q：为什么选择 MPL-2.0 许可证？**

A：本项目公开可读的源代码，便于审查、修改和复现。选择 MPL-2.0，是希望在允许商业使用和应用集成的同时，使受该许可证覆盖文件的修改在对外分发时仍能以源代码形式提供，便于修复共享和后续维护。

具体使用与分发要求请以 [MPL-2.0 许可证原文](./LICENSE)为准。科学模型和历史资料的来源及各自适用条件见[第三方声明](./THIRD_PARTY_NOTICES.zh-CN.md)。

**Q：已经有其他轻量天文库和民俗日历库，为什么还要开发这个库？**

A：项目最初计划将 C++ 版本的 [taiyin-ephemeris](https://github.com/RedSC1/taiyin-ephemeris) 移植到 JavaScript，提供与 [py-ephemeris](https://github.com/RedSC1/py-ephemeris) 类似的其他语言实现。考虑到浏览器对包体积和运行成本的要求，后来逐步形成了独立的轻量实现。如果未来有完整移植 C++ 版本的实际需求，计划沿用旧实现的 `js-ephemeris` 名称和原仓库发布，与本项目的轻量版本分别维护。

本项目将天体位置、天象事件、历史历法和传统排盘所需的时间计算整合在同一套星历与时间核心上。行星和月球模型在生成阶段进行筛选和 DE441 校准，并将修正折叠进发布的系数表。项目包含天文年 -6000～10000 范围内的对照测试，但不同天体、年代和接口的精度并不相同，具体见[精度说明](./docs/accuracy.md)。

**Q：古代历法数据是如何组织的？**

A：查询时不重新执行整套古历近似算法，而是读取预先整理的朔、气归日结果。数据采用分段线性基线与稀疏位图保存 ±1 日修正：一张位图记录修正位置，另一张记录修正符号。

这种表示有利于控制数据体积和查询成本，但分段主要服务于压缩，不应直接解释为历史历法模型的分期。古历资料与原始算法的来源见[第三方声明](./THIRD_PARTY_NOTICES.zh-CN.md)。

**Q：为什么只有每日宜忌，没有时辰宜忌？**

A：当前只实现了能够说明资料来源和规则依据的每日宜忌。对于时辰宜忌，尚未整理出足够明确、可复核且适合直接实现的规则体系。因此暂不收录，也不以自行推定的规则填补空缺。后续是否支持，将取决于资料整理和规则验证的进展。

**Q：节日名称和月历显示如何处理？**

A：项目分别整理节日的正式名称、月历短名称、别名和显示优先级，并对部分纪念日进行补充和校正。详情页可展示完整名称和多条记录；月历格选择优先级最高、适合紧凑显示的短名称，避免同一格内堆叠多个标签。

**Q：天体位置采用哪些模型？**

A：水星、金星、地球和火星以 VSOP2013 为理论来源，木星、土星、天王星和海王星以 TOP2013 为理论来源。生成阶段将这些模型转换、筛选为日心黄道经度、黄纬和距离的直接级数，再按 DE441 校准。水星至海王星最终统一使用儒略千年 `T` 的时间幂乘周期项表示。

截断时，同一频率跨多个时间幂的系数作为完整包络保留，避免破坏长期抵消关系。生成器形成嵌套的包络优先级，重排各阶 Lₙ/Bₙ/Rₙ 系数块，并保存各档位的保留项数；运行时按计数表截取各阶前缀，不再重新排名。通用位置与定气定朔使用各自的精度策略，后者不只是项数不同，详见[时间与历法指南](./docs/time-and-calendar.md)。

月球采用经过截断、重排和校准的 ELP/MPP02 级数，通过共享相位表复用三个坐标的相位计算和解析求导。行星与月球的修正均已写入最终级数。

冥王星单独处理：1600～2200 年采用直接拟合 DE441 的 L/B/R Chebyshev 近似，推荐范围外使用宽年代低精度后备模型。远离推荐区间时误差明显增大，不应将“能够返回结果”视为具有同等精度保证。

**Q：ΔT（TT−UT1）如何计算？**

A：历史时期采用 Stephenson, Morrison & Hohenkerk (2016) 的分段三次多项式。现代部分保存逐年观测估计值和短期预测值，并使用 Catmull–Rom 样条插值。-820 年以前使用二次多项式外推，-820～-720 年平滑衔接到论文模型。

当前控制点包含 IERS 对 2027 年的预测；2027～2028 年通过三次 Hermite 插值过渡，2028 年以后采用论文长期模型，并叠加本项目的约 18.6 年周期经验修正项。该修正属于实验性拟合，有限样本上的表现不能保证未来预测精度，也不构成对物理成因的验证。

未来 ΔT 取决于难以精确预测的地球自转变化，其不确定性不能与天体位置模型的误差混为一谈。项目会随新的观测和预测资料更新相关数据；涉及历史或远期民用时刻时，应同时考虑 ΔT 的不确定性。

**Q：是否提供占星规则或完整占星排盘？**

A：本包提供天体几何位置、视位置基础组件和历法计算，不内置宫位、相位容许度等完整占星规则。小行星接口同样返回通用的三维几何位置，并非只为占星经度计算设计。

**Q：八字部分采用什么规则，如何处理规则差异？**

A：八字计算围绕节气边界、干支推算、时区、太阳时及子时换日规则展开。相关选项和边界应在调用时明确指定，以便复核结果。

神煞规则的初始整理使用过 AI 辅助，后续进行了人工复核并补充测试，但仍不能保证覆盖所有流派或消除全部整理错误。对于明确的实现错误，项目会按缺陷处理；对于规则差异，则需要结合资料来源和所选规则讨论。欢迎通过 issue 提供可复现输入和参考依据。

**Q：JavaScript 版紫微与早期 Dart 版 ziwei_core 的实现为什么不同？**

A：早期 ziwei_core 通过一个小型解释器执行声明式安星规则，以适应不同流派。前端集成后，运行时解析 JSON 并逐条解释规则的额外开销促使项目调整了实现方式。

当前实现将声明式规则预编译为静态查表数据，减少运行时解释工作。旧格式仍受支持，但新规则配置更推荐使用 TOML 文件。

**Q：ziwei-lite 相较 ziwei_core 有哪些主要变化？**

A：主要变化包括规则预编译与静态查表、历史年号展示，以及特殊历史历法月份序列下的流月推演。由于实现语言和运行环境不同，不能仅凭结构调整直接给出跨版本的性能提升比例。

开启历史历法模式后，流月按相应的历史月份序列推演，而不是在遇到特殊月份时直接停止。在支持的天文年 -6000～10000 范围内可进行相关计算；更远年代即使底层仍返回数值，也不建议使用，节气时刻和农历归日不具备相同的验证范围。

**Q：如何理解八字和紫微的排盘准确性？**

A：需要区分天文历算精度、规则实现是否正确，以及所选流派是否一致。八字年、月柱的边界取决于节气；日、时柱还受时区、太阳时和子时换日规则影响。紫微的日期基础依赖农历排月，同时涉及定气与定朔。相关天文模型和测试结果见[文档](./docs/)。

八字神煞主要收录古书可见或流传较广的规则；紫微内置的 TOML 规则包含星曜亮度表、四化表及部分不同版本的四化配置。流派差异不等同于天文计算误差，也不能用来解释所有程序缺陷。排盘计算的一致性并不代表传统术数的现实预测能力已经得到验证。

**Q：历史历法排盘能否与其他软件兼容？**

A：历史模式使用包内整理的朔气归日资料和月份序列，天文事件求根由本项目的实现完成。特殊历法月名和改历边界另行处理并校验，资料来源见[第三方声明](./THIRD_PARTY_NOTICES.zh-CN.md)。

不同软件可能采用不同的历法数据、时区、换日约定和流派规则，因此不承诺结果完全一致。比较时应先对齐输入与配置，再分别检查历算结果和排盘规则。

**Q：为什么研究并实现紫微斗数规则？**

A：作者主要关注其规则系统和程序实现，并不因开发了相关软件就认为其预测能力已经得到验证。

紫微斗数通过出生年月日时、顺逆规则、宫位映射和状态转换构造盘面。这些关系适合用程序形式化，也为规则配置、历史历法边界和一致性测试提供了研究对象。确定性的规则变换不会凭空增加输入所携带的信息；盘面结构复杂，也不意味着其具有相应的现实预测能力。

本项目希望提供可阅读、可复核的规则实现，将对传统文化和算法结构的研究，与对预测效力的判断分别讨论。

算术回历正反转换与时区约定见 [时间与历法文档](docs/time-and-calendar.md#算术回历hijri)，可运行 `node examples/hijri-calendar.mjs` 查看示例。
