feat: 扩展天文计算能力

- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息
- 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算
- 新增木星伽利略卫星位置、现象与接触事件计算
- 新增恒星星表、星座判定、自行修正与观测辅助能力
- 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包
- 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算
- 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试
- 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试
- 更新中文和英文 README,补充示例、精度说明、SVG 配图
This commit is contained in:
2026-05-01 22:38:44 +08:00
parent 98ff574495
commit 3ffdbe0034
365 changed files with 63589 additions and 17508 deletions
+66 -16
View File
@@ -2,6 +2,8 @@ package calendar
import (
"time"
"b612.me/astro/basic"
)
type LunarInfo struct {
@@ -47,18 +49,30 @@ type Time struct {
lunars []LunarTime
}
// Solar 公历时间 / solar time.
//
// 返回内部保存的公历 `time.Time`,不做时区或历法再计算。
func (t Time) Solar() time.Time {
return t.solarTime
}
// Time 公历时间 / solar time.
//
// 是 `Solar` 的同义接口,便于把 `calendar.Time` 当作普通时间对象使用。
func (t Time) Time() time.Time {
return t.solarTime
}
// Lunars 农历候选结果 / lunar candidates.
//
// 返回全部候选农历结果。
func (t Time) Lunars() []LunarTime {
return t.lunars
}
// LunarDesc 农历描述 / lunar descriptions.
//
// 返回全部候选结果的农历描述,如开元二年正月初一;若无年号,则返回年份描述,如二零二五年正月初一。
func (t Time) LunarDesc() []string {
var res []string
for _, v := range t.lunars {
@@ -67,6 +81,9 @@ func (t Time) LunarDesc() []string {
return res
}
// LunarDescWithEmperor 含君主信息的农历描述 / lunar descriptions with emperor.
//
// 返回全部候选结果中含有君主信息的农历描述,如唐玄宗 开元二年正月初一;若无年号,则返回年份描述,如二零二五年正月初一。
func (t Time) LunarDescWithEmperor() []string {
var res []string
for _, v := range t.lunars {
@@ -75,6 +92,9 @@ func (t Time) LunarDescWithEmperor() []string {
return res
}
// LunarDescWithDynasty 含朝代信息的农历描述 / lunar descriptions with dynasty.
//
// 返回全部候选结果中含有朝代信息的农历描述,如唐 开元二年正月初一;若无年号,则返回年份描述,如二零二五年正月初一。
func (t Time) LunarDescWithDynasty() []string {
var res []string
for _, v := range t.lunars {
@@ -83,6 +103,9 @@ func (t Time) LunarDescWithDynasty() []string {
return res
}
// LunarDescWithDynastyAndEmperor 含朝代与君主信息的农历描述 / lunar descriptions with dynasty and emperor.
//
// 返回全部候选结果中含有朝代和君主信息的农历描述,如唐 唐玄宗 开元二年正月初一;若无年号,则返回年份描述,如二零二五年正月初一。
func (t Time) LunarDescWithDynastyAndEmperor() []string {
var res []string
for _, v := range t.lunars {
@@ -91,6 +114,9 @@ func (t Time) LunarDescWithDynastyAndEmperor() []string {
return res
}
// LunarInfo 农历结构化信息 / structured lunar information.
//
// 返回全部候选结果对应的结构化农历信息切片。
func (t Time) LunarInfo() []LunarInfo {
var res []LunarInfo
for _, v := range t.lunars {
@@ -99,6 +125,9 @@ func (t Time) LunarInfo() []LunarInfo {
return res
}
// Eras 朝代、皇帝、年号信息 / era information.
//
// 返回全部候选结果对应的朝代、皇帝、年号信息。
func (t Time) Eras() []EraDesc {
var res []EraDesc
for _, v := range t.lunars {
@@ -107,6 +136,9 @@ func (t Time) Eras() []EraDesc {
return res
}
// Lunar 首个农历结果 / first lunar result.
//
// 若存在多个候选结果,只返回第一个;无结果时返回零值 `LunarTime`。
func (t Time) Lunar() LunarTime {
if len(t.lunars) > 0 {
return t.lunars[0]
@@ -114,6 +146,9 @@ func (t Time) Lunar() LunarTime {
return LunarTime{}
}
// Add 时间偏移 / add a duration.
//
// 返回公历时间偏移后的农历结果。
func (t Time) Add(d time.Duration) Time {
if d < time.Second {
newT := t.solarTime.Add(d)
@@ -123,7 +158,7 @@ func (t Time) Add(d time.Duration) Time {
sec := d.Seconds()
jde := Date2JDE(t.solarTime)
jde += sec / 86400.0
newT := JDE2Date(jde)
newT := basic.JDE2DateByZone(jde, t.solarTime.Location(), true)
rT, _ := SolarToLunar(newT)
return rT
}
@@ -148,7 +183,7 @@ type LunarTime struct {
eras []EraDesc
}
// ShengXiao 生肖
// ShengXiao 生肖 / Chinese zodiac.
func (l LunarTime) ShengXiao() string {
shengxiao := []string{"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"}
diff := l.LunarYear() % 12
@@ -158,73 +193,85 @@ func (l LunarTime) ShengXiao() string {
return shengxiao[diff]
}
// Zodiac 生肖,和生肖同义
// Zodiac 生肖别名 / zodiac alias.
func (l LunarTime) Zodiac() string {
return l.ShengXiao()
}
// GanZhiYear 年干支
// GanZhiYear 年干支 / sexagenary year name.
func (l LunarTime) GanZhiYear() string {
return GanZhiOfYear(l.year)
}
// GanZhiMonth 月干支
// GanZhiMonth 月干支 / sexagenary month name.
func (l LunarTime) GanZhiMonth() string {
return l.ganzhiMonth
}
// GanZhiDay 日干支
// GanZhiDay 日干支 / sexagenary day name.
func (l LunarTime) GanZhiDay() string {
return GanZhiOfDay(l.solarDate)
}
// LunarYear 农历年
// LunarYear 农历年 / lunar year.
func (l LunarTime) LunarYear() int {
return l.year
}
// LunarMonth 农历月
// LunarMonth 农历月 / lunar month.
func (l LunarTime) LunarMonth() int {
return l.month
}
// LunarDay 农历日
// LunarDay 农历日 / lunar day.
func (l LunarTime) LunarDay() int {
return l.day
}
// IsLeap 是否闰月
// IsLeap 是否闰月 / whether the month is leap.
func (l LunarTime) IsLeap() bool {
return l.leap
}
// Eras 朝代、皇帝、年号信息
// Eras 朝代、皇帝、年号信息 / era information.
//
// 返回该农历结果对应的朝代、皇帝、年号信息。
func (l LunarTime) Eras() []EraDesc {
return l.eras
}
// MonthDay 农历月日描述,如正月初一。此处,十一月表示为冬月,十二月表示为腊月
// MonthDay 农历月日描述 / lunar month-day description.
//
// 获取农历月日描述,如正月初一。此处,十一月表示为冬月,十二月表示为腊月。
func (l LunarTime) MonthDay() string {
return l.desc
}
// LunarDesc 获取农历描述,如开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// LunarDesc 农历描述 / lunar descriptions.
//
// 获取农历描述,如开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一。
func (l LunarTime) LunarDesc() []string {
return l.innerDescWithNianHao(false, false)
}
// LunarDescWithEmperor 获取含有君主信息的农历描述,如唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// LunarDescWithEmperor 君主信息的农历描述 / lunar descriptions with emperor.
//
// 获取含有君主信息的农历描述,如唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一。
// 君主信息仅供参考,多个皇帝用同一个年号的场景,此处不准
func (l LunarTime) LunarDescWithEmperor() []string {
return l.innerDescWithNianHao(true, false)
}
// LunarDescWithDynasty 获取含有朝代信息的农历描述,如唐 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// LunarDescWithDynasty 朝代信息的农历描述 / lunar descriptions with dynasty.
//
// 获取含有朝代信息的农历描述,如唐 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一。
func (l LunarTime) LunarDescWithDynasty() []string {
return l.innerDescWithNianHao(false, true)
}
// LunarDescWithDynastyAndEmperor 获取含有朝代和君主信息的农历描述,如唐 唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// LunarDescWithDynastyAndEmperor 朝代和君主信息的农历描述 / lunar descriptions with dynasty and emperor.
//
// 获取含有朝代和君主信息的农历描述,如唐 唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一。
// 君主信息仅供参考,多个皇帝用同一个年号的场景,此处不准
func (l LunarTime) LunarDescWithDynastyAndEmperor() []string {
return l.innerDescWithNianHao(true, true)
@@ -249,6 +296,9 @@ func (l LunarTime) innerDescWithNianHao(withEmperor bool, withDynasty bool) []st
return res
}
// LunarInfo 农历结构化信息 / structured lunar information.
//
// 返回该农历结果对应的结构化农历信息切片;若存在多个并行年号,则会有多条记录。
func (l LunarTime) LunarInfo() []LunarInfo {
var res []LunarInfo
for _, v := range l.eras {