Files
astro/doc/manual/sun-moon.md
T
b612 16c62a97d5 feat: 完善时标与天象几何计算并扩展输出接口
- 新增时标、ΔT 模型、质心时间与 UT1 支持
- 改进日月食、月掩、行星事件及路径边界计算
- 完善恒星三维自行与动态距离传播
- 扩展 SVG、GeoJSON、KML 输出与底层距离换算工具
- 整理中英文手册、示例资源及回归测试
2026-09-23 18:55:12 +08:00

1002 lines
45 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 太阳与月亮
[English](en/sun-moon.md) | [返回 README](../../README.md)
`sun` 与 `moon` 是主链,`lite/sun` 与 `lite/moon` 是独立近似实现。没有特殊说明时,角度单位为度,视直径与视半径为角秒,`sun.EarthDistance` 为 AU、`moon.EarthDistance` 为千米;观测接口的 `time.Time` 通常表示民用时刻,真太阳时的返回值另按地方太阳时解释,见[时标手册](timescale.md)。
本手册覆盖日月本体:位置、升落与中天、站心量、相位与朔望、近远地点与交点、最大赤纬、天平动、视直径与物理星历。日月食几何见[日食与月食手册](eclipse.md#全球见食图与月食出图),月掩见[月掩手册](occultation.md#月掩出图),站心几何与折射的通用换算见[坐标工具](coord.md)。
## 目录
- [日出日落与月相](#日出日落与月相)
- [API 参考](#api-参考)
- [sun](#sun)
- [moon](#moon)
- [lite/sun](#litesun)
- [lite/moon](#litemoon)
- [截断项族](#截断项族)
- [常用场景](#常用场景)
- [今天的日出日落与晨昏朦影](#今天的日出日落与晨昏朦影)
- [月出月落与此刻的月亮高度](#月出月落与此刻的月亮高度)
- [月相与下次朔望弦](#月相与下次朔望弦)
- [视直径、地月距离与天平动](#视直径地月距离与天平动)
- [地心量与站心量的区别](#地心量与站心量的区别)
- [主链与 lite 的误差对照](#主链与-lite-的误差对照)
- [观测角语义](#观测角语义)
- [综合示例:日月升落与位置](#综合示例日月升落与位置)
- [日出日落/月出月落](#日出日落月出月落)
- [日月位置](#日月位置)
- [太阳](#太阳)
- [位置](#位置)
- [升落与中天](#升落与中天)
- [站心量与视差角](#站心量与视差角)
- [真太阳时与均时差](#真太阳时与均时差)
- [物理与视直径](#物理与视直径)
- [地球轨道极值](#地球轨道极值)
- [月亮](#月亮)
- [位置](#位置-1)
- [升落与中天](#升落与中天-1)
- [月相](#月相)
- [近地点与远地点](#近地点与远地点)
- [交点](#交点)
- [最大赤纬](#最大赤纬)
- [天平动与亮边位置角](#天平动与亮边位置角)
- [视直径与地月距离](#视直径与地月距离)
- [轻量链路](#轻量链路)
- [lite/sun](#litesun-1)
- [lite/moon](#litemoon-1)
- [与主链的差异与误差量级](#与主链的差异与误差量级)
- [参数与返回值约定](#参数与返回值约定)
- [单位与角口径](#单位与角口径)
- [时标](#时标)
- [高度与 aero](#高度与-aero)
- [零值与越界](#零值与越界)
- [精度与适用范围](#精度与适用范围)
## 日出日落与月相
```go
package main
import (
"fmt"
"log"
"time"
"b612.me/astro/moon"
"b612.me/astro/sun"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
date := time.Date(2020, 1, 1, 8, 8, 8, 0, cst)
lon, lat, height := 108.93, 34.27, 0.0
rise, err := sun.RiseTime(date, lon, lat, height, true) //日出时间
if err != nil {
log.Fatal(err)
}
set, err := sun.SetTime(date, lon, lat, height, true) //日落时间
if err != nil {
log.Fatal(err)
}
fmt.Println(rise.Format(time.RFC3339), set.Format(time.RFC3339))
fmt.Println(moon.Phase(date), moon.PhaseDesc(date)) //月相(被照亮比例)和月相描述
}
```
`aero=true` 采用含折射的升落判据。极昼、极夜或当天没有事件时,升落接口返回错误。`moon.Phase` 是受照比例,不是月龄。
## API 参考
下表按能力分组列出四个包的导出接口。多数求值接口另有 `...N` 截断变体,统一在[截断项族](#截断项族)里说明;表中所有 `time.Time` 参数都是绝对时刻,`lon`/`lat` 均为东正西负、北正南负。
### sun
| 名称 | 用途 | 单位与口径 |
| --- | --- | --- |
| `TrueLo` / `ApparentLo` | 太阳真黄经 / 视黄经 | 度,地心 |
| `TrueBo` | 太阳真黄纬 | 度,地心;库内不单独提供视黄纬 |
| `GeometricLo` / `MidFunc` | 太阳几何黄经 / 中心差 | 度 |
| `ApparentRa` / `ApparentDec` / `ApparentRaDec` | 太阳视赤经 / 视赤纬 | 度,地心 |
| `EclipticObliquity` | 黄赤交角 | 度;第二参数为 `true` 时加入交角章动 |
| `EclipticNutation` / `EclipticNutation1980` | 黄经章动 | 度,IAU 2000B / IAU 1980 |
| `AxialtiltNutation` / `AxialtiltNutation1980` | 交角章动 | 度,IAU 2000B / IAU 1980 |
| `RiseTime` / `SetTime` | 日出 / 日落 | `(time.Time, error)`;`aero` 与 `height` 见参数与返回值约定 |
| `DownTime` | 日落别名 | 已废弃,内部转调 `SetTime` |
| `CulminationTime` | 上中天 | `time.Time` |
| `MorningTwilight` / `EveningTwilight` | 晨光始 / 暮光终 | `(time.Time, error)`;角度常用 -6 / -12 / -18 度 |
| `Altitude` / `Zenith` / `Azimuth` / `HourAngle` | 几何高度角 / 天顶距 / 方位角 / 时角 | 度,站心 |
| `ApparentAltitude` / `ApparentZenith` | 视高度角 / 视天顶距 | 度;需要气压 hPa 与气温 ℃ |
| `ParallacticAngle` | 视差角(天顶方向角) | 度,有符号 |
| `ApparentSolarTime` | 真太阳时 | `time.Time`,结果时区按经度换算 |
| `EquationTime` | 均时差 | 小时 |
| `Diameter` / `Semidiameter` | 视直径 / 视半径 | 角秒 |
| `EarthDistance` | 日地距离 | AU |
| `Physical` | 日面物理量 | 返回 `PhysicalInfo`,字段单位为度 |
### moon
| 名称 | 用途 | 单位与口径 |
| --- | --- | --- |
| `TrueLo` / `TrueBo` / `ApparentLo` | 地心真黄经 / 真黄纬 / 视黄经 | 度 |
| `TrueRa` / `TrueDec` / `TrueRaDec` | 地心真赤道坐标 | 度 |
| `GeocentricApparentRa` / `GeocentricApparentDec` / `GeocentricApparentRaDec` | 地心视赤道坐标 | 度 |
| `ApparentRa` / `ApparentDec` / `ApparentRaDec` | 站心视赤道坐标 | 度;需要观测者经纬度 |
| `Altitude` / `Zenith` / `Azimuth` / `HourAngle` | 站心高度角 / 天顶距 / 方位角 / 时角 | 度 |
| `ApparentAltitude` / `ApparentZenith` | 视高度角 / 视天顶距 | 度;需要气压 hPa 与气温 ℃ |
| `ParallacticAngle` | 视差角 | 度,有符号,显式依赖观测者经纬度 |
| `RiseTime` / `SetTime` | 月出 / 月落 | `(time.Time, error)` |
| `DownTime` | 月落别名 | 已废弃,内部转调 `SetTime` |
| `CulminationTime` | 上中天 | `time.Time`;需要经度与纬度 |
| `Phase` / `PhaseDesc` | 受照比例 / 中文月相描述 | 比例 `[0,1]` / 字符串 |
| `SunMoonLoDiff` | 日月视黄经差 | 度,`[0,360)` |
| `ShuoYue` / `ShangXianYue` / `WangYue` / `XiaXianYue` | 以小数年为锚点的朔 / 上弦 / 望 / 下弦 | `time.Time`,UTC |
| `NewMoon` / `FullMoon` / `FirstQuarter` / `LastQuarter` | 上四相的英文 alias | `time.Time`,UTC |
| `Next*` / `Last*` / `Closest*` | 下一次 / 上一次 / 最近一次相位与最大赤纬 | `time.Time`;结果保持输入时区 |
| `NextConjunctionWithPlanet` / `LastConjunctionWithPlanet` / `ClosestConjunctionWithPlanet` | 行星合月(赤经合) | `time.Time`;目标用 `ConjunctionPlanet` 常量 |
| `PerigeesInMonth` / `ApogeesInMonth` | 指定年月内的近地点 / 远地点 | `[]ApsisInfo`,距离 km |
| `MaximumNorthDeclinationsInMonth` / `MaximumSouthDeclinationsInMonth` | 指定年月内的最大北 / 南赤纬事件 | `[]MaximumDeclinationInfo`,赤纬为度 |
| `AscendingNode` / `DescendingNode` | 升交点 / 降交点黄经 | 度 |
| `Physical` / `TopocentricPhysical` | 地心 / 站心天平动与自转轴位置角 | 返回 `PhysicalInfo`,字段单位为度 |
| `BrightLimbPositionAngle` / `TopocentricBrightLimbPositionAngle` | 地心 / 站心亮边位置角 | 度 |
| `Diameter` / `Semidiameter` | 视直径 / 视半径 | 角秒 |
| `EarthDistance` | 地月距离 | 千米 |
`moon` 还提供月掩接口,其参数、结果和完整示例见[月掩手册](occultation.md)。
| 分组 | 导出接口与类型 |
| --- | --- |
| 事件与路径 | `FindStarOccultations`, `FindPlanetOccultations`, `FindBestStarOccultations`, `FindBestPlanetOccultations`, `FindStarOccultationPaths`, `FindPlanetOccultationPaths` |
| 瞬时足迹与视圆几何 | `StarOccultationFootprintAt`, `PlanetOccultationFootprintsAt`, `StarOccultationDiagram`, `PlanetOccultationDiagram` |
| UT1 标签换算 | `StarOccultationInfoInUT1`, `StarOccultationPathInUT1`, `PlanetOccultationInfoInUT1`, `PlanetOccultationPathInUT1` |
| 恒星结果 | `StarOccultationInfo`, `StarOccultationPath`, `StarOccultationInstant` |
| 行星结果 | `PlanetOccultationInfo`, `PlanetOccultationPath`, `PlanetOccultationInstant`, `PlanetOccultationFootprint` |
| 路径数据 | `OccultationFootprint`, `OccultationPathPoint`, `OccultationGreatestTimeContour`, `OccultationRiseSetCurve` |
| 搜索与路径选项 | `OccultationSearchOptions`, `OccultationPathOptions`, `OccultationPathAlgorithm` |
| 视圆图数据 | `StarOccultationDiagramFrame`, `StarOccultationDiagramOptions`, `StarOccultationDiagramResult`, `PlanetOccultationDiagramFrame`, `PlanetOccultationDiagramOptions`, `PlanetOccultationDiagramResult` |
| 目标与坐标 | `StarData`, `StarCoordinate`, `StarCoordinateFromStarData`, `Observer`, `CoordinateFrame`, `CoordinateFrameICRS`, `CoordinateFrameJ2000`, `CoordinateFrameApparentOfDate` |
| 事件类型 | `OccultationPlanet`, `OccultationType`, `OccultationTotal`, `OccultationPartial`, `OccultationGrazing` |
| 路径算法 | `OccultationPathAlgorithmOptimized`, `OccultationPathAlgorithmExact` |
| 升落阶段 | `RiseSetPhase`, `RiseSetDirection`, `RiseSetPhaseStart`, `RiseSetPhaseGreatest`, `RiseSetPhaseEnd`, `RiseSetDirectionRise`, `RiseSetDirectionSet` |
| 错误 | `ErrInvalidOccultationInput`, `ErrOccultationPathSamplingLimit` |
行星目标常量为 `OccultationMercury` 至 `OccultationNeptune`。
### lite/sun
| 名称 | 用途 | 单位与口径 |
| --- | --- | --- |
| `TrueLo` / `ApparentLo` | 轻量真黄经 / 视黄经 | 度,地心 |
| `TrueRa` / `TrueDec` / `TrueRaDec` | 轻量真赤道坐标 | 度,地心 |
| `ApparentRa` / `ApparentDec` / `ApparentRaDec` | 轻量视赤道坐标 | 度,地心 |
| `Distance` | 轻量日地距离 | AU |
| `HourAngle` / `Azimuth` / `Altitude` / `Zenith` | 轻量时角 / 方位角 / 高度角 / 天顶距 | 度,站心 |
| `RiseTime` / `SetTime` | 轻量日出 / 日落 | `(time.Time, error)` |
| `ERR_SUN_NEVER_RISE` / `ERR_SUN_NEVER_SET` | 极夜 / 极昼 | 错误值 |
### lite/moon
| 名称 | 用途 | 单位与口径 |
| --- | --- | --- |
| `TrueLo` / `TrueBo` | 轻量地心真黄经 / 真黄纬 | 度 |
| `TrueRa` / `TrueDec` / `TrueRaDec` | 轻量地心真赤道坐标 | 度 |
| `ApparentRa` / `ApparentDec` / `ApparentRaDec` | 轻量站心视赤道坐标 | 度;需要观测者经纬度 |
| `HourAngle` / `Azimuth` / `Altitude` / `Zenith` | 轻量时角 / 方位角 / 高度角 / 天顶距 | 度,站心 |
| `SunMoonLoDiff` / `Phase` / `PhaseAge` | 轻量日月黄经差 / 受照比例 / 月龄 | 度 / `[0,1]` / 天 |
| `RiseTime` / `SetTime` | 轻量月出 / 月落 | `(time.Time, error)` |
| `ERR_MOON_NEVER_RISE` / `ERR_MOON_NEVER_SET` / `ERR_NOT_TODAY` | 极夜 / 极昼 / 事件不在当天 | 错误值 |
### 截断项族
`sun` 与 `moon` 的多数求值接口提供 `...N` 变体:名字是原接口名加 `N`,参数在末尾多一个 `n int`,返回形状不变。`n < 0` 使用当前仓库内嵌的全部解析项,结果与不带 `N` 的版本一致;`n >= 0` 把级数截断到 `n` 项,适合性能对比、批量粗算或误差敏感性实验。
- sun:`TrueLoN`、`TrueBoN`、`AltitudeN`、`ZenithN`、`AzimuthN`、`HourAngleN`、`ParallacticAngleN`、`ApparentAltitudeN`、`ApparentZenithN`、`DiameterN`、`SemidiameterN`、`PhysicalN`、`RiseTimeN`、`SetTimeN`、`DownTimeN`、`CulminationTimeN`、`MorningTwilightN`、`EveningTwilightN`、`ApparentSolarTimeN`
- moon:`TrueLoN`、`TrueBoN`、`AscendingNodeN`、`DescendingNodeN`、`DiameterN`、`SemidiameterN`、`PhysicalN`、`TopocentricPhysicalN`、`BrightLimbPositionAngleN`、`TopocentricBrightLimbPositionAngleN`
站心赤道坐标(`ApparentRa` / `ApparentDec` / `ApparentRaDec`)、月亮的升落(`RiseTime` / `SetTime`)与相位族没有 `N` 变体,它们不受截断开关控制。
## 常用场景
### 今天的日出日落与晨昏朦影
```go
fmt.Println(sun.MorningTwilight(date, lon, lat, -6)) // 民用晨光始
fmt.Println(sun.RiseTime(date, lon, lat, height, true))
fmt.Println(sun.SetTime(date, lon, lat, height, true))
fmt.Println(sun.EveningTwilight(date, lon, lat, -6)) // 民用暮光终
```
```text
2020-01-01 07:22:28.138198256 +0800 CST <nil>
2020-01-01 07:49:52.591398954 +0800 CST <nil>
2020-01-01 17:45:09.366609156 +0800 CST <nil>
2020-01-01 18:12:33.801986575 +0800 CST <nil>
```
朦影角度换成 `-12` / `-18` 就是航海与天文朦影;`aero = true` 按蒙气差与视半径修正后的地平求升落,与几何地平的差别见[升落与中天](#升落与中天)。
### 月出月落与此刻的月亮高度
```go
rise, _ := moon.RiseTime(date, lon, lat, height, true)
set, _ := moon.SetTime(date, lon, lat, height, true)
fmt.Println(rise)
fmt.Println(set)
fmt.Println(moon.Altitude(date, lon, lat), moon.Azimuth(date, lon, lat))
```
```text
2020-01-01 11:52:50.042243599 +0800 CST
2020-01-01 23:26:49.498263895 +0800 CST
-45.349728852972675 67.63824603392399
```
月球升落按当地自然日计算,升落之间可以没有连续性,`date` 之后的完整周期要看升起与落下时刻的先后关系,细节见[日出日落/月出月落](#日出日落月出月落);高度角为负说明月亮在地平线下,这里 `-45.35°` 就是此刻看不见。
### 月相与下次朔望弦
```go
fmt.Println(moon.Phase(date), moon.PhaseDesc(date)) // 受照比例与月相名
fmt.Println(moon.NextShuoYue(date)) // 下次朔
fmt.Println(moon.NextWangYue(date)) // 下次望
```
```text
0.30004130960877884 上峨眉月
2020-01-25 05:41:58.271192908 +0800 CST
2020-01-11 03:21:17.159625291 +0800 CST
```
`Next*` / `Last*` / `Closest*` 是下一次 / 上一次 / 最近一次三种检索口径,上弦与下弦分别是 `moon.NextShangXianYue` / `moon.NextXiaXianYue`;结果保持输入时区,四种相位与朔望月的完整口径见[月相](#月相)。
### 视直径、地月距离与天平动
```go
fmt.Println(moon.Diameter(date), moon.EarthDistance(date))
p := moon.Physical(date)
fmt.Println(p.LibrationLongitude, p.LibrationLatitude, p.PositionAngle)
```
```text
1774.6658461637385 404238.6096080479
0.7655535663486027 6.382898400777244 -23.672356410246774
```
`Diameter` 单位角秒、`EarthDistance` 单位千米;`1774.67″`(约 29.6′)对应约 40.4 万 km 的远地点附近,比平均视直径小约 5%。`Physical` 给地心天平动,站心版本 `TopocentricPhysical` 与字段口径见[天平动与亮边位置角](#天平动与亮边位置角)。
### 地心量与站心量的区别
```go
geoRa, geoDec := moon.GeocentricApparentRaDec(date) // 地心视位置
topRa, topDec := moon.ApparentRaDec(date, lon, lat) // 站心视位置
fmt.Printf("geocentric %.4f %.4f\n", geoRa, geoDec)
fmt.Printf("topocentric %.4f %.4f\n", topRa, topDec)
fmt.Printf("delta dRA=%.4f dDec=%.4f\n", topRa-geoRa, topDec-geoDec)
fmt.Println(sun.ApparentRaDec(date)) // 太阳只给地心量
```
```text
geocentric 349.2322 -9.9506
topocentric 349.7343 -10.3485
delta dRA=0.5021 dDec=-0.3978
280.8950939694744 -23.05840775453492
```
月亮离得近,站心与地心能差半度左右(这里赤经差 `0.50°`、赤纬差 `0.40°`),合起来比一个月面视直径还大,所以给观测者用的位置必须走 `moon.ApparentRaDec`;太阳在 1 AU 外视差可忽略,只提供地心量(当然也可以调用站心坐标转换接口得到站心位置=-=)。口径定义见[观测角语义](#观测角语义)。
### 主链与 lite 的误差对照
```go
fmt.Println(sun.Altitude(date, lon, lat), litesun.Altitude(date, lon, lat)) // 主链 / 轻量几何高度角
fmt.Println(moon.Phase(date), litemoon.Phase(date)) // 受照比例
fmt.Println(litemoon.PhaseAge(date)) // 轻量月龄(天)
fmt.Println(litesun.RiseTime(date, lon, lat, height, true)) // 轻量日出
```
```text
2.40091496867759 2.403576774819768
0.30004130960877884 0.2978124633132848
5.42608394367707
2020-01-01 07:49:51.69717729 +0800 CST <nil>
```
轻量链路与主链形状同构、精度不同:同一时刻的高度角只差 `0.0027°` 量级,月相只差 `0.0022`;2026 全年 8 站点统计下 `lite/sun` 日出平均绝对误差 `0.02 min`(P95 `0.04 min`、最大 `0.31 min`),`lite/moon` 月出 `0.28 min`(P95 `0.57 min`、最大 `1.44 min`),`lite/moon` 的 `Phase()` 最大绝对误差 `0.00243`。
完整对照与截断误差见[与主链的差异与误差量级](#与主链的差异与误差量级)与 README 的 [Lite 轻量链路](accuracy.md#lite-轻量链路)。
## 观测角语义
- `Altitude`:高度角,地平线为 `0°`,天顶为 `+90°`
- `Zenith`:天顶距,天顶为 `0°`,地平线为 `90°`
- `Zenith` 与 `Altitude` 互补,两者相加为 `90°`
- `Azimuth`:方位角,正北为 `0°`,向东增加,取值范围 `[0°, 360°)`
- `HourAngle`:时角,上中天为 `0°`,向西(下午)增大,归一化到 `[0°, 360°)`
- `ParallacticAngle`:视差角(天顶方向角),有符号,单位度;方向定义与站心几何的统一口径见[坐标工具](coord.md)
- `Altitude` / `Azimuth` 是几何中心高度与方位,不含大气折射和视半径修正;`ApparentAltitude` / `ApparentZenith` 加入大气折射,需要传入气压(hPa)与气温(℃)
- 太阳的赤道坐标是地心量;月亮的 `TrueRaDec` 与 `GeocentricApparentRaDec` 是地心量,`ApparentRa` / `ApparentDec` / `ApparentRaDec` 是站心量,必须给出观测者经纬度
## 综合示例:日月升落与位置
下面两个完整示例覆盖最常用的入口,公共前置是西安(`108.93°E, 34.27°N`)与 `2020-01-01 08:08:08 CST`。后续各节的片段都省略这类公共变量,只保留与本组能力相关的语句。
### 日出日落/月出月落
> ⚠️ 月球升降时间按当天日期计算,升降时间点之间不一定具有连续性。
>
> 例如月亮可能在凌晨1点落下、中午12点再次升起,此时升起时间会晚于降落时间;这一场景晚上的月落时间对应次日日期。
>
> 完整的升降周期由升起时间与降落时间的先后关系决定:判断升起时间是否在降落时间之后,即可确定后续的正确时间点。
```go
package main
import (
"fmt"
"time"
"b612.me/astro/moon"
"b612.me/astro/sun"
)
func main() {
// 以陕西省西安市为例,设置西安市经纬度,设置地平高度为0米
var lon, lat, height float64 = 108.93, 34.27, 0
cst := time.FixedZone("CST", 8*3600)
// 指定 2020-01-01 08:08:08 CST,所有"今日"语义都以这个本地自然日为基准。
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
// 西安市2020年1月1日民用晨朦影开始时间
// 民用朦影,太阳位于地平线下6度,航海朦影=地平线下12度,天文朦影=地平线下18度
fmt.Println(sun.MorningTwilight(date, lon, lat, -6))
// 西安市2020年1月1日日出时间,按动态标准折射和实时太阳视半径计算上缘过地平线
fmt.Println(sun.RiseTime(date, lon, lat, height, true))
// 西安市2020年1月1日太阳上中天时间
fmt.Println(sun.CulminationTime(date, lon))
// 西安市2020年1月1日日落时间,按动态标准折射和实时太阳视半径计算上缘过地平线
fmt.Println(sun.SetTime(date, lon, lat, height, true))
// 西安市2020年1月1日民用昏朦影结束时间
fmt.Println(sun.EveningTwilight(date, lon, lat, -6))
// 西安市2020年1月1日月出时间,按动态标准折射和实时月球视半径计算上缘过地平线
fmt.Println(moon.RiseTime(date, lon, lat, height, true))
// 西安市2020年1月1日月亮上中天时间
fmt.Println(moon.CulminationTime(date, lon, lat))
// 西安市2020年1月1日月落时间,按动态标准折射和实时月球视半径计算上缘过地平线
fmt.Println(moon.SetTime(date, lon, lat, height, true))
}
```
输出结果:
```text
2020-01-01 07:22:27.960488498 +0800 CST <nil>
2020-01-01 07:49:52.413689196 +0800 CST <nil>
2020-01-01 12:47:35.933117866 +0800 CST
2020-01-01 17:45:09.188657999 +0800 CST <nil>
2020-01-01 18:12:33.624035418 +0800 CST <nil>
2020-01-01 11:52:49.860912859 +0800 CST <nil>
2020-01-01 17:36:48.811488747 +0800 CST
2020-01-01 23:26:49.313553571 +0800 CST <nil>
```
### 日月位置
```go
package main
import (
"fmt"
"time"
"b612.me/astro/moon"
"b612.me/astro/star"
"b612.me/astro/sun"
"b612.me/astro/tools"
)
func main() {
// 以陕西省西安市为例,设置西安市经纬度,设置地平高度为0米
var lon, lat float64 = 108.93, 34.27
cst := time.FixedZone("CST", 8*3600)
// 指定观测时刻。
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
// 太阳此刻的视黄经,单位度。
fmt.Println(sun.ApparentLo(date))
// 此刻黄赤交角,第二个参数 true 表示使用真黄赤交角。
fmt.Println(sun.EclipticObliquity(date, true))
//太阳此刻视赤经、视赤纬
ra, dec := sun.ApparentRaDec(date)
fmt.Println("赤经:", tools.Format(ra/15, 1), "赤纬:", tools.Format(dec, 0))
//太阳当前所在星座
fmt.Println(star.Constellation(ra, dec, date))
//此刻西安市的太阳方位角、高度角、天顶距
fmt.Println("方位角:", sun.Azimuth(date, lon, lat), "高度角:", sun.Altitude(date, lon, lat), "天顶距:", sun.Zenith(date, lon, lat))
//此刻日地距离,单位为天文单位(AU)
fmt.Println(sun.EarthDistance(date))
//月亮此刻站心视赤经、视赤纬
ra, dec = moon.ApparentRaDec(date, lon, lat)
fmt.Println("赤经:", tools.Format(ra/15, 1), "赤纬:", tools.Format(dec, 0))
//月亮当前所在星座
fmt.Println(star.Constellation(ra, dec, date))
//此刻西安市的月亮方位角、高度角、天顶距
fmt.Println("方位角:", moon.Azimuth(date, lon, lat), "高度角:", moon.Altitude(date, lon, lat), "天顶距:", moon.Zenith(date, lon, lat))
//此刻地月距离,单位为千米
fmt.Println(moon.EarthDistance(date))
}
```
输出结果:
```text
280.01526210031136
23.4362178391013
赤经: 18h43m34.82s 赤纬: -23°3′30.27″
人马座
方位角: 120.19477090015224 高度角: 2.4014437419430097 天顶距: 87.59855625805699
0.983292937163176
赤经: 23h18m56.24s 赤纬: -10°20′54.42″
宝瓶座
方位角: 67.63889332004852 高度角: -45.34916937173283 天顶距: 135.34916937173284
404238.6096080479
```
## 太阳
本节片段省略公共前置:`cst := time.FixedZone("CST", 8*3600)`、`date := time.Date(2026, 1, 1, 12, 0, 0, 0, cst)`、`var lon, lat float64 = 108.93, 34.27`(西安),并假定已导入 `fmt`、`time`、`sun`、`moon`。
### 位置
太阳位置接口只依赖绝对时刻,不依赖观测者。真黄纬由 `TrueBo` 给出,库内不单独提供视黄纬;`EclipticObliquity` 的第二个参数决定是否加入交角章动。
```go
// 太阳真黄经、视黄经与真黄纬,单位度。
fmt.Println(sun.TrueLo(date), sun.ApparentLo(date), sun.TrueBo(date))
// 太阳视赤经与视赤纬。
ra, dec := sun.ApparentRaDec(date)
fmt.Println("视赤经:", ra, "视赤纬:", dec)
fmt.Println(sun.ApparentRa(date), sun.ApparentDec(date))
// 黄赤交角、几何黄经与中心差。
fmt.Println(sun.EclipticObliquity(date, true), sun.GeometricLo(date), sun.MidFunc(date))
```
输出结果:
```text
280.742671383543 280.7383965677222 0.00018280886212040676
视赤经: 281.6786097810291 视赤纬: -23.00369182413533
281.6786097810291 -23.00387403948847
23.438148552330773 280.83169623098 -0.08703499790144194
```
同一族接口都提供 `...N` 截断变体。下面的对照用 `n = 8` 截断,`n < 0` 时结果与不带 `N` 的版本逐位一致:
```go
// n<0 使用全部内嵌 VSOP 项,n>=0 截断解析项。
fmt.Println(sun.TrueLo(date), sun.TrueLoN(date, 8))
fmt.Println(sun.Altitude(date, lon, lat), sun.AltitudeN(date, lon, lat, 8))
fmt.Println(sun.Diameter(date), sun.DiameterN(date, 8))
```
输出结果:
```text
280.742671383543 280.7439900413756
31.61569462953789 31.615524473491835
1950.9979407481142 1950.9994358395434
```
### 升落与中天
`RiseTime` / `SetTime` 以 `date` 所在时区的当地自然日为锚点,返回值保持同一个时区;`height` 是按椭球高(大地高)解读的观测点高程,单位米。`aero` 为 `true` 时按动态标准大气折射与实时视半径计算**上缘**过地平线,为 `false` 时只做几何中心高度过地平线的判定。
朦影接口把目标高度角作为参数:民用朦影 `-6°`、航海朦影 `-12°`、天文朦影 `-18°`,晨昏两侧分别是 `MorningTwilight` 与 `EveningTwilight`。
```go
// 民用、航海、天文晨朦影的目标高度角。
for _, angle := range []float64{-6, -12, -18} {
t, err := sun.MorningTwilight(date, lon, lat, angle)
fmt.Println(angle, t.Format("15:04:05"), err)
}
// 上中天与日出;极区无事件时 err 非空。
fmt.Println(sun.CulminationTime(date, lon).Format("15:04:05"))
t, err := sun.RiseTime(date, lon, lat, 0, true)
fmt.Println(t.Format("15:04:05"), err)
```
输出结果:
```text
-6 07:22:47 <nil>
-12 06:51:31 <nil>
-18 06:21:00 <nil>
12:47:50
07:50:10 <nil>
```
### 站心量与视差角
`Altitude` / `Zenith` / `Azimuth` / `HourAngle` 走几何链路,不含折射;`ApparentAltitude` / `ApparentZenith` 加入大气折射,需要给气压与气温;`ParallacticAngle` 是有符号的视差角。站心几何与折射的更一般换算(含大气折射、站心赤道坐标)见[坐标工具](coord.md)。
```go
fmt.Println(sun.Azimuth(date, lon, lat), sun.Altitude(date, lon, lat), sun.Zenith(date, lon, lat))
fmt.Println(sun.ApparentAltitude(date, lon, lat, 1010, 10), sun.ApparentZenith(date, lon, lat, 1010, 10))
// 时角与有符号视差角。
fmt.Println(sun.HourAngle(date, lon, lat), sun.ParallacticAngle(date, lon, lat))
```
输出结果:
```text
167.09774780715728 31.61569462953789 58.38430537046211
31.643010360459822 58.356989639540174
348.07820699607544 -11.564174033740159
```
### 真太阳时与均时差
`ApparentSolarTime` 返回给定经度处的真太阳时,结果时区是按经度换算出来的固定偏移时区,不是调用方传入的时区;`EquationTime` 给出同一时刻的均时差,单位小时。`sundial.TrueSolarTime` 与 `ApparentSolarTime` 口径相同,`sundial` 另提供地方平太阳时与日晷几何,见[日晷与真太阳时](sundial.md)。
```go
// 真太阳时;结果时区按经度换算。
fmt.Println(sun.ApparentSolarTime(date, lon).Format("2006-01-02 15:04:05 -0700"))
// 均时差,单位小时。
fmt.Println(sun.EquationTime(date))
// sundial.TrueSolarTime 与其口径相同。
fmt.Println(sundial.TrueSolarTime(date, lon).Format("2006-01-02 15:04:05 -0700"))
```
输出结果:
```text
2026-01-01 11:12:18 +0715
-0.05674946079069686
2026-01-01 11:12:18 +0715
```
### 物理与视直径
`sun.Physical` 返回 `PhysicalInfo`:`P` 是太阳北极位置角,`B0` 是日面中心的太阳纬度,`L0` 是日面中心的卡林顿经度,单位都是度。`Diameter` / `Semidiameter` 给视直径与视半径,单位角秒;`EarthDistance` 给日地距离,单位 AU。
```go
// 视直径、视半径(角秒)与日地距离(AU)。
fmt.Println(sun.Diameter(date), sun.Semidiameter(date), sun.EarthDistance(date))
// 日面物理量 P/B0/L0,单位度。
p := sun.Physical(date)
fmt.Println(p.P, p.B0, p.L0)
```
输出结果:
```text
1950.9979407481142 975.4989703740571 0.9833237486528845
1.979086377118846 -3.0131029209723916 296.9595333604375
```
日、月与七大行星的同名接口形状一致,可以并排对照:
```go
fmt.Println(sun.Diameter(date), sun.Semidiameter(date))
fmt.Println(sun.Physical(date))
fmt.Println(moon.Diameter(date), moon.Semidiameter(date))
fmt.Println(mars.Diameter(date), mars.Semidiameter(date))
```
### 地球轨道极值
日地距离的极值由 `earth` 包给出,时间按 UTC,距离单位 AU;只关心某一时刻的轨道偏心率时直接调 `EarthEccentricity`:
```go
// 2026 年地球近日点、远日点,时间为 UTC,距离单位 AU。
peri := earth.Perihelion(2026)
aphe := earth.Aphelion(2026)
fmt.Printf("earth perihelion=%s distance=%.9fAU\n", peri.Time.Format(time.RFC3339), peri.Distance)
fmt.Printf("earth aphelion=%s distance=%.9fAU\n", aphe.Time.Format(time.RFC3339), aphe.Distance)
```
输出结果:
```text
earth perihelion=2026-01-03T17:15:35Z distance=0.983302050AU
earth aphelion=2026-07-06T17:31:24Z distance=1.016643936AU
```
```go
fmt.Printf("earth e=%.9f\n", earth.EarthEccentricity(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)))
```
## 月亮
本节的片段沿用太阳一节的公共前置,`date` 仍是 `2026-01-01 12:00:00 CST`、观测点是西安。
### 位置
月亮的赤道坐标分三层:`TrueRaDec` 是地心真位置,`GeocentricApparentRaDec` 是地心视位置,`ApparentRaDec` 是站心视位置。黄道侧只有地心量:`TrueLo` 真黄经、`TrueBo` 真黄纬、`ApparentLo` 视黄经。
```go
// 地心真赤道坐标。
fmt.Println(moon.TrueRaDec(date))
// 地心视赤道坐标。
fmt.Println(moon.GeocentricApparentRaDec(date))
// 站心视赤道坐标。
fmt.Println(moon.ApparentRaDec(date, lon, lat))
// 真黄经、真黄纬与视黄经。
fmt.Println(moon.TrueLo(date), moon.TrueBo(date), moon.ApparentLo(date))
```
输出结果:
```text
66.66309709020791 26.830370234236764
66.66476688311091 26.830608930005567
67.0275694157259 25.982665403390747
69.21422925147913 5.060516750865828 69.21574418700706
```
### 升落与中天
月球升落与太阳一样以当地自然日为锚点:`RiseTime` / `SetTime` 返回当天的事件时刻,`CulminationTime` 返回当天上中天时刻。月球的升降之间可以没有连续性,`date` 之后的完整周期要靠升起时间与降落时间的先后关系决定;当某个事件落在查询日期之外时,升落接口返回 `ERR_NOT_TODAY`。
```go
// 月出、上中天与月落,按当天日期计算。
rise, err := moon.RiseTime(date, lon, lat, 0, true)
fmt.Println(rise.Format("15:04:05"), err)
fmt.Println(moon.CulminationTime(date, lon, lat).Format("15:04:05"))
set, err := moon.SetTime(date, lon, lat, 0, true)
fmt.Println(set.Format("15:04:05"), err)
```
输出结果:
```text
16:17:11 <nil>
00:03:16
06:41:37 <nil>
```
### 月相
`Phase` 返回 `[0,1]` 的受照比例,`PhaseDesc` 返回中文月相名,`SunMoonLoDiff` 返回归一化到 `[0,360)` 的日月视黄经差(朔附近接近 `0°`、望附近接近 `180°`)。`Next*` / `Last*` / `Closest*` 是三种检索口径,结果保持输入时区;四个相位同时提供拼音名与英文 alias,例如 `ShuoYue` / `NewMoon`、`WangYue` / `FullMoon`、`ShangXianYue` / `FirstQuarter`、`XiaXianYue` / `LastQuarter`。
```go
package main
import (
"fmt"
"time"
"b612.me/astro/moon"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
// 指定观测时刻。
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
//月亮此刻被照亮的比例(月相)
fmt.Println(moon.Phase(date))
//月相具体描述
fmt.Println(moon.PhaseDesc(date))
//下次朔月时间;也可用 moon.NextNewMoon(date)
fmt.Println(moon.NextShuoYue(date))
//下次上弦月时间;也可用 moon.NextFirstQuarter(date)
fmt.Println(moon.NextShangXianYue(date))
//下次望月时间;也可用 moon.NextFullMoon(date)
fmt.Println(moon.NextWangYue(date))
//下次下弦月时间;也可用 moon.NextLastQuarter(date)
fmt.Println(moon.NextXiaXianYue(date))
}
```
输出结果:
```text
0.30004130960877884 // 月面约有 30% 被太阳照亮
上峨眉月 // 当前月相描述
2020-01-25 05:41:58.271192908 +0800 CST // 下一次朔月
2020-01-03 12:45:23.229190707 +0800 CST // 下一次上弦
2020-01-11 03:21:17.159625291 +0800 CST // 下一次望月,也就是满月
2020-01-17 20:58:23.396406769 +0800 CST // 下一次下弦
```
`Last*`、`Closest*` 与按小数年锚点求解的 `ShuoYue` / `FullMoon` 等返回 UTC;`ClosestConjunctionWithPlanet` 求最近一次行星合月,目标用 `ConjunctionPlanet` 常量给出:
```go
// 朔与望的上一次、最近一次。
fmt.Println(moon.LastShuoYue(date), moon.ClosestShuoYue(date))
fmt.Println(moon.LastWangYue(date), moon.ClosestWangYue(date))
// 上弦与下弦。
fmt.Println(moon.LastFirstQuarter(date), moon.ClosestLastQuarter(date))
// 以小数年为锚点的解,结果为 UTC。
fmt.Println(moon.ShuoYue(2025.5).Format(time.RFC3339), moon.FullMoon(2025.5).Format(time.RFC3339))
// 最近一次行星合月(赤经合)。
fmt.Println(moon.ClosestConjunctionWithPlanet(date, moon.ConjunctionJupiter))
```
输出结果:
```text
2025-12-20 09:43:19.074603617 +0800 CST 2025-12-20 09:43:19.074603617 +0800 CST
2025-12-05 07:14:03.670351803 +0800 CST 2026-01-03 18:02:53.55531156 +0800 CST
2025-12-28 03:09:50.141303837 +0800 CST 2026-01-10 23:48:22.03346461 +0800 CST
2025-06-25T10:31:35Z 2025-07-10T20:36:46Z
2026-01-04 05:59:19.9425897 +0800 CST
```
### 近地点与远地点
`PerigeesInMonth` / `ApogeesInMonth` 返回指定公历月内的全部近地点与远地点事件,元素是 `ApsisInfo`,含 `Time`(UTC)与 `Distance`(km),一个月可能有零个、一个或多个事件。
```go
// 2026 年 1 月的月球近地点、远地点,距离单位 km。
perigees := moon.PerigeesInMonth(2026, time.January)
apogees := moon.ApogeesInMonth(2026, time.January)
fmt.Printf("moon perigee=%s distance=%.1fkm count=%d\n", perigees[0].Time.Format(time.RFC3339), perigees[0].Distance, len(perigees))
fmt.Printf("moon apogee=%s distance=%.1fkm count=%d\n", apogees[0].Time.Format(time.RFC3339), apogees[0].Distance, len(apogees))
```
输出结果:
```text
moon perigee=2026-01-01T21:44:24Z distance=360348.1km count=2
moon apogee=2026-01-13T20:47:13Z distance=405437.9km count=1
```
### 交点
月球也提供升交点和降交点黄经,适合做食季、轨道几何和月球轨道研究:
```go
nodeDate := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(moon.AscendingNode(nodeDate), moon.DescendingNode(nodeDate))
```
这里的“升交点 / 降交点”与行星章节中的定义相同:
- `AscendingNode`:月球轨道从黄道南侧穿到黄道北侧时的黄经
- `DescendingNode`:月球轨道从黄道北侧穿到黄道南侧时的黄经
- 单位都是度;同一时刻两者通常相差约 `180°`
以上面 `nodeDate := 2026-01-01 00:00:00 UTC` 的示例来说,输出结果是:
```text
340.95708624505863 160.9570862450587
```
### 最大赤纬
月球赤纬在一个交点月内达到南北极值,`MaximumDeclinationInfo` 含 `Time`(事件时刻)与 `Declination`(该时刻的地心赤纬,度)。逐月接口返回当月全部事件,`Next*` / `Last*` / `Closest*` 按时刻检索:
```go
// 最近最大北赤纬与上一次最大南赤纬。
north := moon.ClosestMaximumNorthDeclination(date)
south := moon.LastMaximumSouthDeclination(date)
fmt.Println(north.Time.Format(time.RFC3339), north.Declination)
fmt.Println(south.Time.Format(time.RFC3339), south.Declination)
// 下一次最大北赤纬与当月全部事件。
fmt.Println(moon.NextMaximumNorthDeclination(date).Time.Format(time.RFC3339))
events := moon.MaximumNorthDeclinationsInMonth(2026, time.January)
fmt.Println(len(events))
for _, event := range events {
fmt.Println(event.Time.Format(time.RFC3339), event.Declination)
}
```
输出结果:
```text
2026-01-02T16:10:49+08:00 28.266373428242343
2025-12-20T07:06:57+08:00 -28.23514705130737
2026-01-02T16:10:49+08:00
2 2026-01-02T08:10:49Z 28.266373428242343
```
同一组事件的逐月列表口径如下(`2026-01-01 00:00:00 UTC` 输入):
```go
// 2026 年 1 月的月球最大北/南赤纬。
north := moon.MaximumNorthDeclinationsInMonth(2026, time.January)
south := moon.MaximumSouthDeclinationsInMonth(2026, time.January)
fmt.Printf("north=%s dec=%.6f\n", north[0].Time.Format(time.RFC3339), north[0].Declination)
fmt.Printf("south=%s dec=%.6f\n", south[0].Time.Format(time.RFC3339), south[0].Declination)
```
输出结果:
```text
north=2026-01-02T08:10:49Z dec=28.266373
south=2026-01-16T05:15:14Z dec=-28.304184
```
### 天平动与亮边位置角
`Physical` 返回地心天平动,`TopocentricPhysical` 返回站心天平动,二者都是 `PhysicalInfo`,含光学、物理与总天平动的经纬分量以及自转轴位置角 `PositionAngle`,单位度。亮边位置角的 `0°` 从月面北点起、向东增加。
```go
// 地心天平动与自转轴位置角。
p := moon.Physical(date)
fmt.Println(p.LibrationLongitude, p.LibrationLatitude, p.PositionAngle)
// 站心天平动与自转轴位置角。
topo := moon.TopocentricPhysical(date, lon, lat, 0)
fmt.Println(topo.LibrationLongitude, topo.LibrationLatitude, topo.PositionAngle)
// 地心与站心亮边位置角。
fmt.Println(moon.BrightLimbPositionAngle(date), moon.TopocentricBrightLimbPositionAngle(date, lon, lat, 0))
```
输出结果:
```text
-0.9680924808747591 -6.547834757841939 -9.025022841390472
-0.7780085060449551 -5.659649431558411 -8.883877708625544
269.08333384819935 267.8559531949645
```
站心量的完整示例(上海,`height = 4 m`):
```go
// 月球天平动和自转轴位置角。
physical := moon.Physical(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC))
fmt.Printf("libration lon=%.6f lat=%.6f pa=%.6f\n", physical.LibrationLongitude, physical.LibrationLatitude, physical.PositionAngle)
// 月亮明亮边缘位置角;0° 从月面北点起,向东增加。
fmt.Printf("bright limb=%.6f\n", moon.BrightLimbPositionAngle(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)))
// 上海站心看到的月球天平动、自转轴位置角和亮边位置角。
topo := moon.TopocentricPhysical(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC), 121.4737, 31.2304, 4)
fmt.Printf("topo libration lon=%.6f lat=%.6f pa=%.6f\n", topo.LibrationLongitude, topo.LibrationLatitude, topo.PositionAngle)
fmt.Printf("topo bright limb=%.6f\n", moon.TopocentricBrightLimbPositionAngle(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC), 121.4737, 31.2304, 4))
```
输出结果:
```text
libration lon=-1.278902 lat=-6.531444 pa=-9.967050
bright limb=267.364849
topo libration lon=-1.736754 lat=-5.780730 pa=-10.072846
topo bright limb=266.038258
```
### 视直径与地月距离
`Diameter` / `Semidiameter` 给视直径与视半径(角秒),`EarthDistance` 给地月距离(千米)。三者都只依赖绝对时刻:
```go
// 视直径、视半径(角秒)与地月距离(千米)。
fmt.Println(moon.Diameter(date), moon.Semidiameter(date), moon.EarthDistance(date))
```
输出结果:
```text
1986.4975069969655 993.2487534984828 360488.4234539985
```
## 轻量链路
`lite/sun` 与 `lite/moon` 是独立于主链的近似实现:不依赖 VSOP87 或主链的 ELP2000/82 级数,面向 CPU / 内存受限环境,调用方式与主链同形。升落搜索用固定步长扫描加二分,不走主链的高精度章动迭代。
```go
package main
import (
"fmt"
"time"
litemoon "b612.me/astro/lite/moon"
litesun "b612.me/astro/lite/sun"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
date := time.Date(2026, 1, 1, 20, 0, 0, 0, cst)
fmt.Println(litesun.Altitude(date, 121.4737, 31.2304))
fmt.Println(litesun.RiseTime(date, 121.4737, 31.2304, 0, true))
fmt.Println(litemoon.Phase(date))
fmt.Println(litemoon.PhaseAge(date))
fmt.Println(litemoon.RiseTime(date, 121.4737, 31.2304, 0, true))
}
```
下面的片段沿用这一节的公共前置:上海(`121.4737°E, 31.2304°N`)与 `2026-01-01 20:00:00 CST`。
### lite/sun
轻量太阳链路提供黄经、赤道坐标、距离、地平坐标与升落,但不提供视直径、日面物理量与朦影接口。`Distance` 是日地距离(AU):需要注意,主链同名能力叫 `EarthDistance`,轻量链路叫 `Distance`。
```go
// 轻量太阳真黄经、视黄经与日地距离(AU)。
fmt.Println(litesun.TrueLo(date), litesun.ApparentLo(date), litesun.Distance(date))
// 轻量视赤经与视赤纬。
ra, dec := litesun.ApparentRaDec(date)
fmt.Println(ra, dec)
// 轻量时角、方位角、高度角与天顶距。
fmt.Println(litesun.HourAngle(date, 121.4737, 31.2304), litesun.Azimuth(date, 121.4737, 31.2304), litesun.Altitude(date, 121.4737, 31.2304), litesun.Zenith(date, 121.4737, 31.2304))
// 轻量升落。
fmt.Println(litesun.RiseTime(date, 121.4737, 31.2304, 0, true))
fmt.Println(litesun.SetTime(date, 121.4737, 31.2304, 0, true))
```
输出结果:
```text
281.0835889076667 281.0793650422643 0.9833163427233701
282.0475744673639 -22.973803828458102
120.58011725187828 263.4579582386061 -37.07676039520773 127.07676039520773
2026-01-01 06:52:24.6475178 +0800 CST <nil>
2026-01-01 17:02:44.014452695 +0800 CST <nil>
```
### lite/moon
轻量月球链路提供少量摄动项的月球位置、轻量站心修正、月相与月龄、升落,但不提供天平动、视直径、地月距离与交点。`PhaseAge` 返回月龄(天),只在轻量链路提供:
```go
// 轻量真黄经与真黄纬。
fmt.Println(litemoon.TrueLo(date), litemoon.TrueBo(date))
// 轻量地心真赤道坐标。
ra, dec := litemoon.TrueRaDec(date)
fmt.Println(ra, dec)
// 轻量站心视赤道坐标。
fmt.Println(litemoon.ApparentRaDec(date, 121.4737, 31.2304))
// 日月黄经差、受照比例与月龄。
fmt.Println(litemoon.SunMoonLoDiff(date), litemoon.Phase(date), litemoon.PhaseAge(date))
// 轻量地平坐标。
fmt.Println(litemoon.Altitude(date, 121.4737, 31.2304), litemoon.Azimuth(date, 121.4737, 31.2304), litemoon.Zenith(date, 121.4737, 31.2304))
```
输出结果:
```text
74.25630740893 5.078407838127742
72.2518040645064 27.549605139478064
72.74256784654426 27.432483413326057
153.17694236666568 0.9462021494002484 12.565014741082448
63.55513206820331 90.53047230027812 26.444867931796693
```
### 与主链的差异与误差量级
轻量链路与主链的差别集中在实现与误差上,接口形状基本一致。位置与月相等纯求值接口相对主链约快 `8.3–27.3x`,升落接口约 `1.0–3.7x`,计算链路零堆分配;升落搜索步长为 `lite/sun` `30` 分钟、`lite/moon` `15` 分钟。与 `sun` / `moon` 的误差(2026 全年,8 个站点)如下,数据见[适用范围与精度](accuracy.md#lite-轻量链路):
| 能力 | 平均绝对误差 | P95 | 最大绝对误差 |
| --- | --- | --- | --- |
| `lite/sun` 日出 | `0.02 min` | `0.04 min` | `0.31 min` |
| `lite/sun` 日落 | `0.02 min` | `0.06 min` | `0.35 min` |
| `lite/moon` 月出 | `0.28 min` | `0.57 min` | `1.44 min` |
| `lite/moon` 月落 | `0.36 min` | `0.86 min` | `1.24 min` |
| `lite/moon` `Phase()` | `0.00089` | `0.00185` | `0.00243` |
| `lite/moon` `PhaseAge()` | `0.003 d` | `0.010 d` | `0.014 d` |
| `lite/moon` 地心黄经 | `2.41'` | `6.82'` | `9.91'` |
| `lite/moon` 地心黄纬 | `0.87'` | `1.83'` | `2.92'` |
两个包都不提供 `...N` 截断族。太阳侧的极夜 / 极昼错误是 `ERR_SUN_NEVER_RISE` / `ERR_SUN_NEVER_SET`;月球侧除 `ERR_MOON_NEVER_RISE` / `ERR_MOON_NEVER_SET` 外还有 `ERR_NOT_TODAY`,语义与主链一致。
## 参数与返回值约定
### 单位与角口径
- 角度一律为度,`RA`、`Lon`、`Azimuth` 归一化到 `[0°, 360°)`,赤纬与黄纬取值 `[−90°, 90°]`
- 视直径与视半径为角秒;`sun.EarthDistance` 为 AU,`moon.EarthDistance` 为千米
- `Phase` 是 `[0,1]` 的受照比例,`PhaseAge`(轻量链路)为天,`EquationTime` 为小时
- 距离类极值:`earth.Perihelion` / `earth.Aphelion` 为 AU,`ApsisInfo.Distance` 为千米
### 时标
观测输入与事件时刻采用民用时间约定;本库将 `1972-01-01` 以前的读数按 UT1 处理。`ApparentSolarTime` 另返回地方太阳时读数。`time.Time` 携带的时区只影响“当地自然日”的划分与返回值的时区,不改变绝对时刻。UT1 与图内时标的完整声明见[时标声明](map-geojson.md#时标声明)。
### 高度与 aero
- 升落接口的 `height` 是按椭球高(大地高)解读的观测点高程,单位米,不是正高;换算约定见[观测点高度约定](coord.md#观测点高度)
- `aero = true`:按动态标准大气折射与实时视半径计算上缘过地平线;`aero = false`:只做几何中心高度过地平线的判定
- `ApparentAltitude` / `ApparentZenith` 的 `pressureHPa`、`temperatureC` 是观测时的气压(hPa)与气温(℃)
### 零值与越界
- 极夜时升落接口返回 `ERR_SUN_NEVER_RISE` / `ERR_MOON_NEVER_RISE`;极昼时返回 `ERR_SUN_NEVER_SET` / `ERR_MOON_NEVER_SET`,此时第一个返回值为零值 `time.Time`
- 朦影不存在时返回 `ERR_TWILIGHT_NOT_EXISTS`
- 月亮升降事件落在查询日期之外时返回 `ERR_NOT_TODAY`,对应上面“月出月落按当天日期计算”的语义
- `DownTime` / `DownTimeN` 是 `SetTime` 的废弃别名,`ERR_SUN_NEVER_DOWN` / `ERR_MOON_NEVER_DOWN` 是极昼错误的废弃别名,新代码不应使用
- `...N` 中 `n < 0` 用全部内嵌项、`n >= 0` 截断;`n` 只影响级数长度,不改变返回单位与时区
### 精度与适用范围
太阳与行星用内置 VSOP87 解析项,月球用内置 ELP2000/82 风格截断级数,覆盖 J2000 前后约 4000 年,无需外部星历文件。截断误差、月球链路的能力边界和 lite 链路的量化误差见[适用范围与精度](accuracy.md)。本手册的太阳 / 月球接口适合历法、观测辅助、科普与业余预报;航天导航、精确掩星预报和严格动力学积分需要 JPL DE 等专业星历。