Astro
Astro: Go Astronomy Algorithms Library - Chinese Lunar Calendar, Solar/Lunar Eclipses, Sun/Moon/Planet Positions, Rise/Set, Planet Events, Stars, Coordinates, Orbits, Sundials and Lightweight Ephemerides (天文算法 Go 库:农历、日月食、日月行星位置、升落、行星天象、恒星、坐标、轨道、日晷与轻量星历)
Install / Use
npx skills add Starainrt/astroInstalls into whichever agent you are using.
README
Astro
English | 中文
自用多年的天文算法库,用于个人天文历法爱好、科普演示和轻量研究。
📚 本项目主要用于天文算法学习与验证,计算结果满足业余爱好级别需求。
基于《天文算法》(Astronomical Algorithms)一书实现,提供历法转换、太阳/月亮/行星位置、日月食、月掩、升落、中天、月相、恒星、坐标变换、物理星历、研究公式和通用小天体轨道传播等功能。太阳和行星部分使用内置 VSOP87 解析项,月球部分使用内置 ELP2000/82 解析级数,不依赖外部 JPL 星历文件。
没有特殊标注时,本程序所提供的坐标均为瞬时天球坐标;角度单位默认是度,视直径/视半径单位是角秒,距离单位按函数名使用 AU 或 km。
目录
安装
go get github.com/starainrt/astro
功能概览
- 📅 历法转换:公历与农历互转(公元前721年-公元3000年或更久)、节气时刻
- 🌞 太阳计算:天球位置、日出日落、日地距离、真太阳时、视高度角、视差角、日面物理参数(
P/B0/L0)、视直径等 - 🌙 月亮计算:天球位置、月出月落、地月距离、月相、朔望时间、视直径、亮边位置角、视差角、地心/站心天平动、近远地点、交点、最大赤纬等
- 🪶 轻量链路:
lite/sun与lite/moon提供面向手表、前端、小程序和其它资源受限环境的轻量近似太阳/月亮算法,覆盖天球位置、升落和月相 - 🌗 日月食:全局日食、站心日食、中心线/偏食足迹、月食、地方可见月食,以及局地示意图和全球见食图 SVG
- 🌘 月掩:按指定赤经赤纬搜索恒星月掩,按有限圆盘计算行星月掩,支持指定地点接触时刻、全球掩带、几何掩甚点和 SVG
- 🗺️ 地理输出:日食、月食和月掩结果可编码为带时间数据与可选时间标记的 GeoJSON;全球 SVG 使用无行政边界海岸线,并支持等经纬和南北极投影
- 🪐 行星计算:七大行星天球位置、升落时间、合冲留、大距、水星/金星地心凌日等特殊天象时间、升交点/降交点、视直径/视半径、相位、视差角、节点、视星等与物理星历
- ⭐ 恒星计算:指定天球坐标所属星座;同时包含9100颗恒星数据库,可计算升降时间、视差角和视高度角,获取指定日期的恒星坐标信息
- 🧭 坐标工具:黄道/赤道/地平坐标转换、站心坐标、恒星时、岁差、章动、角距离、大气折射、大气质量、视差角、银道坐标
- 🔭 研究公式:黑体辐射、会合周期、星等距离换算、望远镜极限星等、恒星半径/温度/光度换算、大气质量模型
- ☄️ 通用轨道:给定小行星、彗星或假想天体轨道根数,计算日心/地心位置和站心视位置,并提供距日/距地距离、日距角、相位角、照明比例、H-G 视星等和轻量视双星位置角/角距计算
- 🕰️ 日晷:真/平太阳时换算、太阳时角、平太阳时/区时时角、平面日晷几何、赤道/水平/垂直日晷特例
包概览
| 包 | 主要能力 |
| --- | --- |
| calendar | 公历/农历互转、节气、历史朝代年号、古代历法信息 |
| coord | 黄道/赤道/地平互转、恒星时、岁差、章动、站心坐标、大气折射、大气质量、视差角、银道坐标、手动黄赤交角和手动时角的研究接口 |
| sun | 太阳位置、日出日落、晨昏朦影、均时差、真太阳时、视高度角、视差角、视直径、日面 P/B0/L0 |
| moon | 月亮位置、月出月落、月相、朔望弦、视高度角、视差角、视直径、亮边位置角、地心/站心天平动、近远地点、交点、最大赤纬,以及恒星/行星月掩和全球掩带 |
| lite/sun / lite/moon | 轻量太阳/月亮近似链路,面向分钟级升落、轻量天球位置和月相计算 |
| eclipse / eclipse/svg | 全局/局地日月食、日食中心线与偏食足迹、局地可见性筛选、局地示意图与全球见食图 SVG |
| moon/svg | 指定地点恒星/行星月掩视圆图,以及带掩带、中心线和时间标记的全球投影 SVG |
| geojson | 将日食、月食和月掩的既有地理结果编码为 RFC 7946 GeoJSON,投影与样式由应用负责 |
| mercury / venus | 水星、金星位置、升落、合日、留、大距、地心凌日、相位、视差角、视星等、视直径、节点和物理星历 |
| mars / jupiter / saturn / uranus / neptune | 外行星位置、升落、合冲、留、方照、相位、视差角、视星等、视直径、节点和物理星历 |
| earth | 地球轨道偏心率、近日点、远日点 |
| star | 星座判定、恒星数据库、恒星自行/岁差/章动修正、恒星升落、视差角、视高度角 |
| formula | 与具体日期无关的常用研究公式和天文奥赛公式,含大气质量模型 |
| orbit | 通用日心二体圆锥曲线轨道传播,支持椭圆、近抛物、抛物和双曲轨道;另含相位/测光辅助和轻量视双星计算 |
| sundial | 真/平太阳时换算、太阳时角、平太阳时/区时时角、平面日晷几何、时间线/赤纬曲线采样、赤道/水平/垂直日晷特例 |
很多接口额外提供 ...N 截断版本:
n < 0:使用本仓库当前内置的全部解析项n >= 0:截断解析项,适合性能对比、粗算或算法研究
这里的“全部解析项”指package中已经内置的表项,不等同于外部发行版 VSOP/ELP 长表的全部原始数据。
大气质量接口的补充:
coord.Airmass...面向观测场景,既可以直接传入视高度角,也可以从真高度角先做折射修正再计算formula.Airmass...只提供纯公式本身,不负责折射修正,适合已经在别处拿到视高度角或天顶距时直接调用
适用范围与精度
太阳与行星
太阳和行星使用内置 VSOP87 解析项,当前表项覆盖 J2000 前后约 4000 年。精度量级如下:
| 目标 | 黄经/黄纬 | 距离 |
| --- | --- | --- |
| 太阳/地球 | 约 0.1" | 约 0.1 × 10^-6 AU |
| 水星、金星 | 约 0.2" | 约 0.2 × 10^-6 AU |
| 火星 | 约 0.5" | 约 1 × 10^-6 AU |
| 木星 | 约 0.5" | 约 3 × 10^-6 AU |
| 土星 | 约 0.5" | 约 5 × 10^-6 AU |
| 天王星 | 约 1" | 约 20 × 10^-6 AU |
| 海王星 | 约 1" | 约 40 × 10^-6 AU |
这类精度适合常规天文历法、观测辅助、科普展示和个人研究。如果需要航天导航、掩星预报或严格动力学积分,应使用 JPL DE 等专业星历。
月球
月球使用内置的 ELP/MPP02 DE405 解析级数(截断版,保留主要周期项),库体积轻,不需要外部星历文件。它适合农历定朔、月相、升落、月食、业余月掩预报和常规位置计算;若需要极高精度月球测距、长期物理天平动或专业掩星,请以 JPL 星历或专门月球星历为准。
Lite 轻量链路
lite/sun 和 lite/moon 是独立于 sun / moon 的近似实现。不依赖 VSOP87 或 ELP2000/82,适合 CPU / 内存受限环境。
lite/sun:简化太阳真黄经 / 视黄经公式 + 轻量赤道坐标转换lite/moon:Schlyter 风格月球近似(约 15 个摄动项)+ 轻量站心修正- 升落搜索:固定步长扫描 + 二分,不走主链的高精度章动迭代
- 计算链路零堆分配(0 allocs/op),月球位置约 1µs,比主链快 20–60 倍
能力边界:
| 包 | 位置模型 | 升落搜索 | 主要用途 |
| --- | --- | --- | --- |
| lite/sun | 简化太阳真/视黄经 + 轻量赤道坐标转换 | 30 分钟步长扫描 + 二分 | 日出日落、太阳高度角、表盘/前端周期刷新 |
| lite/moon | Schlyter / vFPS 月球近似 + 轻量站心修正 | 15 分钟步长扫描 + 二分 | 月出月落、月相、月龄、轻量月球观测辅助 |
与主链 sun / moon 的误差(2026 全年,8 个站点;升落每 7 或 15 天取样,月相月龄每 6 小时):
| 能力 | 平均绝对误差 | P95 | 最大绝对误差 | 备注 |
| --- | --- | --- | --- | --- |
| lite/sun 日出 | 0.02 min | 0.04 min | 0.31 min | 样本中无事件存在性分歧 |
| lite/sun 日落 | 0.02 min | 0.06 min | 0.35 min | 2 个高纬样本在跨午夜“归属哪一天”上有语义差异 |
| lite/moon 月出 | 0.28 min | 0.57 min | 1.44 min | 样本中无事件存在性分歧 |
| lite/moon 月落 | 0.36 min | 0.86 min | 1.24 min | 1 个高纬样本在“当天是否有月落”上与主链判断不同 |
| lite/moon Phase() | 0.00089 | 0.00185 | 0.00243 | 和 moon.Phase 对比 |
| lite/moon PhaseAge() | 0.003 d | 0.010 d | 0.014 d | 约平均 4.3 分钟、P95 14.4 分钟、最大 20.2 分钟 |
| lite/moon 地心黄经 | 2.41' | 6.82' | 9.91' | 相对主链月球位置 |
| lite/moon 地心黄纬 | 0.87' | 1.83' | 2.92' | 相对主链月球位置 |
本地 Go testing.Benchmark 参考值(绝对值因机器而异,相对趋势稳定):
| 接口 | 主链 | lite | 加速倍数 | 主链分配 | lite 分配 |
| --- | --- | --- | --- | --- | --- |
| Sun ApparentRaDec | 13.392 µs/op | 231.0 ns/op | 57.97x | 0 B/op, 0 allocs/op | 0 B/op, 0 allocs/op |
| Sun Altitude | 16.405 µs/op | 681.5 ns/op | 24.09x | 0 B/op, 0 allocs/op | 0 B/op, 0 allocs/op |
| Sun RiseTime | 202.994 µs/op | 18.823 µs/op | 10.78x | 0 B/op, 0 allocs/op | 0 B/op, 0 allocs/op |
| Moon ApparentRaDec | 65.273 µs/op | 1.035 µs/op | 63.06x | 297202 B/op, 70 allocs/op | 0 B/op, 0 allocs/op |
| Moon Phase | 40.264 µs/op | 940.6 ns/op | 42.83x | 178321 B/op, 42 allocs/op | 0 B/op, 0 allocs/op |
| Moon Altitude | 44.883 µs/op | 2.275 µs/op | 19.73x | 178321 B/op, 42 allocs/op | 0 B/op, 0 allocs/op |
| Moon RiseTime | 659.886 µs/op | 77.600 µs/op | 8.50x | 2377613 B/op, 560 allocs/op | 0 B/op, 0 allocs/op |
需要日月食、物理天平动或高纬边界判定时,仍用主链 sun / moon。
精度校验参考
下面这些函数曾与 JPL Horizons、NASA GSFC 等资料对照,可作为使用时判断结果量级的参考:
- 太阳/行星/月亮视直径:与外部基线最大差异从
0.000002"到0.194598"不等,月亮因视差和距离变化更敏感 - 太阳物理星历
P/B0/L0:最大差异约0.003349° / 0.003986° / 0.047394° - 行星升/中天/落:已用 JPL Horizons 电视事件(TVH, Time-Varying Hourly)做对比校验;该基线按 1 分钟步长生成,当前结果与 Horizons 事件时间在分钟级上对齐
- 月出/月落:
aero=true按动态标准折射和实时月球视半径计算上缘过地平线。7 个地点、14 个海平面事件相对 JPL Horizons DE441 的平均/最大差异约0.30s / 0.75s - 月出/月落的其他口径:相对固定
-0.8333°的 MET Norway(Skyfield 1.53 + DE440s)约38.77s / 76.22s;相对未公开地平线口径的 IMCCE Miriade 平均约2m13.46s,61°N低仰角样本最大约6m41.82s - 月掩恒星全球路径:
2025-06-05月掩进贤增九(HR 4799)样例相对项目记录的参考值,掩始/掩甚/掩终差异约+2.30s / -1.37s / -3.12s;掩甚经纬度差异约+0.0122° / +0.0105°,掩带宽为3582.4 km,与参考3571.9 km相差约10.5 km - 地球近日点/远日点:时刻最大差异约
1m28.84s,距离最大差异约0.000000039837 AU - 月球主链位置:当前算法为 ELP/MPP02 DE405 解析级数截断版;在
-2000年四个 JPL/HorizonsJDTT样本上,相对 JPL/Horizons 的最大差异约为黄经219.6"、黄纬25.8"、距离34.3 km - 月球近地点/远地点:时刻最大差异约
15m53.45s,距离最大差异约39.758 km - 月球最大赤纬:时刻最大差异约
2.43s,赤纬最大差异约0.00006431°
站心时角修复后的影响边界:月出/月落、指定地点月掩、月球站心坐标,以及地方月食结果中的食甚月高和可见性判断使用修复后的 UT 时角链。日食和月食的全球接触时刻、食甚、食分等主体结果来自各自的地心/贝塞尔几何,不经过该站心转换,因此现有 NASA 精度数据无需随之改写。
快速开始
历法转换与节气
本 package 支持公历与中国传统农历日期之间的相互转换,并提供节气信息。支持年份范围为公元前721年至公元3000年(部分现代算法可更久)。
农历本质上是阴阳合历(Lunisolar Calendar),但为兼顾大众习惯与代码简洁性,相关函数命名采用 Lunar 而非更学术的 Lunisolar。
历法说明
- 默认路由:按年份自动选择,先秦段使用春秋/古六历重建,
-220..-104使用秦汉颛顼历,-103..1912使用历表,1913年后使用现代算法。 - 显式古历:如果需要指定某一古历系统,请使用
SolarToLunarWithCalendar/LunarToSolarWithCalendar这类 API。 - 数据来源:古历部分主要参考《寿星天文历》;使用 ytliu0教授的网站数据做验证;现代段依据GB/T 33661-2017编排,通过 VSOP87、ELP定气定朔 。
- 节气:
JieQi返回现代天文计算的节气时刻;CalendricalJieQi返回历法相符节气日期。
使用须知
1. 同一公历日期可能对应多个农历日期
在多个政权并存的历史时期(如三国时期),不同政权可能使用不同历法,造成同一公历日期对应多个农历日期。本程序尽可能提供所有可能的转换结果。
2. 同一农历日期可能对应多个公历日期
不仅因多个政权历法不同,同一政权在历法改革中也可能出现此类情况。例如,武则天改历后,圣历三年出现了两个腊月。
3. 公历历法处理规则
本程序基于儒略日进行计算,公历部分处理规则如下:
- 1582年10月15日之后:使用格里高利历
- 1582年10月4日之前:使用儒略历
- 公元8年之前:使用逆推儒略历
- 1582年10月4日的下一天为1582年10月15日
- 1582年10月5日到10月14日这10个公历日期不存在,相关接口会直接拒绝
- 年份表示:0年表示公元前1年,-1年表示公元前2年,以此类推
4. 时区说明
本 package 主要面向中国历法,因此定气和定朔的计算默认采用北京时间(UTC+8)。对于使用其他时区的地区,若直接套用中国农历的编排规则,可能会产生日期偏差。
为方便探索与研究,本 package 提供了底层方法 Solar 和 Lunar,它们支持在自定义时区下,按照**现行中国农历算法(GB/T 33661-2017)**进行公历与农历的相互转换。
如果只需北京时间下的标准转换,请直接使用封装好的 SolarToLunar 和 LunarToSolar 方法。
示例:农历规则要求冬至必须落在农历十一月。以1984年冬至为例,计算可得:
ws := calendar.JieQi(1984, 270)
fmt.Println(ws)
fmt.Println(moon.ClosestShuoYue(ws))
| 节令 | 东八区 (UTC+8) | 东七区 (UTC+7) | |------|----------------|----------------| | 冬至 | 1984-12-22 | 1984-12-21 | | 朔日 | 1984-12-22 | 1984-12-22 |
可见,对于东八区(中国),1984年12月22日既是冬至又是朔日,因此该日为农历十一月初一;而在东七区,冬至提前至12月21日,导致12月22日已成为腊月初一。
类似地,春节的日期也会相差一天。1985年正月初一对应的公历日期,在东八区为2月20日,在东七区则为1月21日:
fmt.Println(calendar.Solar(1985, 1, 1, false, 8.0))
fmt.Println(calendar.Solar(1985, 1, 1, false, 7.0))
5. Go 语言特别注意
⚠️ Go 标准库 time.Time 在历法处理上与本程序存在差异:
- Go 语言在1582年10月15日之前使用逆推格里高利历,而非儒略历。若不使用
Add方法,一般可正常使用。 - 因此,在1582年10月15日之前,
time.Time.Weekday()返回结果与本程序计算结果不一致。 例如:1582年10月4日,本程序为星期四,Go 语言判断为星期一。
建议解决方案:
如需获得与本程序一致的星期数,可使用如下方法:
// date 应为当日0时的 time.Time
weekday := int(calendar.Date2JDE(date)+1.5) % 7
// 0表示星期日,1表示星期一,……,6表示星期六
若在1582年之前使用 time.Time 的 Add 或 AddDate 方法,请注意其在某些年份可能不准确。 例如:700年儒略历为闰年,而 Go 使用的逆推格里高利历中700年不是闰年。
历法转换
公历转农历
- 输入:公历日期 (
time.Time) - 输出:
calendar.Time对象,可能包含多个对应的农历日期 - 功能:可从返回对象中获取:
- 农历日期的详细描述
- 年、月、日的天干地支
- 所属朝代、皇帝、年号等信息
- 完整的结构化农历信息
农历转公历
支持两种调用方式:
方式一:传入农历字符串
支持以下格式(示例):
年号+年+月+日:如"元丰六年十月十二"(闰月前加"闰",日期格式为"初一"、"二十"等)年号+年+月+干支日:如"元嘉二十七年七月庚午"年份+月+日:如"二零二五年正月初一"(闰月前加"闰",适用于现代日期)年份+月+干支日:如"二零二五年正月戊戌日"阿拉伯数字+月+日:可以将中文数字替换为阿拉伯数字,如"2025年1月1日",代表二零二五年正月初一- 注意历史场景:历史上月份名称可能与现代不同(如武则天时期“正月”与“一月”代表不同月份),请使用汉字数字确保准确性
⚠️ 特别提醒: 农历年份与公历年份并非完全重合。例如:公历2025年1月28日(除夕)对应农历2024年
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.7kCommit, push, and open a PR
