1. 补充农历覆盖到公元前104年

2. 农历信息中包含君主、年号、朝代
3. 丰富一些算法,修正一些问题
This commit is contained in:
兔子 2025-09-15 20:55:38 +08:00
parent 438f1700c7
commit d6b6452304
Signed by: b612
GPG Key ID: 99DD2222B612B612
18 changed files with 7048 additions and 458 deletions

View File

@ -34,6 +34,6 @@ func show() {
fmt.Print("农历:") fmt.Print("农历:")
fmt.Println(GetLunar(2019, 10, 23, 8.0/24.0)) fmt.Println(GetLunar(2019, 10, 23, 8.0/24.0))
fmt.Println("当前月出:", JDE2Date(GetMoonRiseTime(jde, 115, 32, 8, 1, 10))) fmt.Println("当前月出:", JDE2Date(GetMoonRiseTime(jde, 115, 32, 8, 1, 10)))
fmt.Println("当前月落:", JDE2Date(GetMoonDownTime(jde, 115, 32, 8, 1, 10))) fmt.Println("当前月落:", JDE2Date(GetMoonSetTime(jde, 115, 32, 8, 1, 10)))
fmt.Println("月相:", MoonLight(jde-8.0/24.0)) fmt.Println("月相:", MoonLight(jde-8.0/24.0))
} }

View File

@ -7,7 +7,7 @@ import (
"time" "time"
) )
var defDeltaTFn = DefaultDeltaT var defDeltaTFn = DefaultDeltaTv2
/* /*
@name: 儒略日计算 @name: 儒略日计算
@ -152,6 +152,93 @@ func DefaultDeltaT(Date float64, IsJDE bool) (Result float64) { //传入年或
return return
} }
func DefaultDeltaTv2(date float64, isJd bool) float64 { //传入年或儒略日,传出为秒
if !isJd {
date = JDECalc(int(date), int((date-math.Floor(date))*12)+1, (date-math.Floor(date))*365.25+1)
}
return DeltaTv2(date)
}
// 使用Stephenson等人(2016)和Morrison等人(2021)的拟合和外推公式计算Delta T
// http://astro.ukho.gov.uk/nao/lvm/
// 2010年后的系数已修改以包含2019年后的数据
// 返回Delta T单位为秒
func DeltaTSplineY(y float64) float64 {
// 积分lod平均太阳日偏离86400秒的偏差方程
// 来自 http://astro.ukho.gov.uk/nao/lvm/
// lod = 1.72 t 3.5 sin(2*pi*(t+0.75)/14) 单位ms/day其中 t = (y - 1825)/100
// 是从1825年开始的世纪数
// 使用 1ms = 1e-3s 和 1儒略年 = 365.25天,
// lod = 6.2823e-3 * Delta y - 1.278375*sin(2*pi/14*(Delta y /100 + 0.75) 单位s/year
// 其中 Delta y = y - 1825。积分该方程得到
// Integrate[lod, y] = 3.14115e-3*(Delta y)^2 + 894.8625/pi*cos(2*pi/14*(Delta y /100 + 0.75)
// 单位为秒。积分常数设为0。
integratedLod := func(x float64) float64 {
u := x - 1825
return 3.14115e-3*u*u + 284.8435805251424*math.Cos(0.4487989505128276*(0.01*u+0.75))
}
if y < -720 {
// 使用积分lod + 常数
const c = 1.007739546148514
return integratedLod(y) + c
}
if y > 2025 {
// 使用积分lod + 常数
const c = -150.56787057979514
return integratedLod(y) + c
}
// 使用三次样条拟合
y0 := []float64{-720, -100, 400, 1000, 1150, 1300, 1500, 1600, 1650, 1720, 1800, 1810, 1820, 1830, 1840, 1850, 1855, 1860, 1865, 1870, 1875, 1880, 1885, 1890, 1895, 1900, 1905, 1910, 1915, 1920, 1925, 1930, 1935, 1940, 1945, 1950, 1953, 1956, 1959, 1962, 1965, 1968, 1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, 2001, 2004, 2007, 2010, 2013, 2016, 2019, 2022}
y1 := []float64{-100, 400, 1000, 1150, 1300, 1500, 1600, 1650, 1720, 1800, 1810, 1820, 1830, 1840, 1850, 1855, 1860, 1865, 1870, 1875, 1880, 1885, 1890, 1895, 1900, 1905, 1910, 1915, 1920, 1925, 1930, 1935, 1940, 1945, 1950, 1953, 1956, 1959, 1962, 1965, 1968, 1971, 1974, 1977, 1980, 1983, 1986, 1989, 1992, 1995, 1998, 2001, 2004, 2007, 2010, 2013, 2016, 2019, 2022, 2025}
a0 := []float64{20371.848, 11557.668, 6535.116, 1650.393, 1056.647, 681.149, 292.343, 109.127, 43.952, 12.068, 18.367, 15.678, 16.516, 10.804, 7.634, 9.338, 10.357, 9.04, 8.255, 2.371, -1.126, -3.21, -4.388, -3.884, -5.017, -1.977, 4.923, 11.142, 17.479, 21.617, 23.789, 24.418, 24.164, 24.426, 27.05, 28.932, 30.002, 30.76, 32.652, 33.621, 35.093, 37.956, 40.951, 44.244, 47.291, 50.361, 52.936, 54.984, 56.373, 58.453, 60.678, 62.898, 64.083, 64.553, 65.197, 66.061, 66.919, 68.130, 69.250, 69.296}
a1 := []float64{-9999.586, -5822.27, -5671.519, -753.21, -459.628, -421.345, -192.841, -78.697, -68.089, 2.507, -3.481, 0.021, -2.157, -6.018, -0.416, 1.642, -0.486, -0.591, -3.456, -5.593, -2.314, -1.893, 0.101, -0.531, 0.134, 5.715, 6.828, 6.33, 5.518, 3.02, 1.333, 0.052, -0.419, 1.645, 2.499, 1.127, 0.737, 1.409, 1.577, 0.868, 2.275, 3.035, 3.157, 3.199, 3.069, 2.878, 2.354, 1.577, 1.648, 2.235, 2.324, 1.804, 0.674, 0.466, 0.804, 0.839, 1.005, 1.348, 0.594, -0.227}
a2 := []float64{776.247, 1303.151, -298.291, 184.811, 108.771, 61.953, -6.572, 10.505, 38.333, 41.731, -1.126, 4.629, -6.806, 2.944, 2.658, 0.261, -2.389, 2.284, -5.148, 3.011, 0.269, 0.152, 1.842, -2.474, 3.138, 2.443, -1.329, 0.831, -1.643, -0.856, -0.831, -0.449, -0.022, 2.086, -1.232, 0.22, -0.61, 1.282, -1.115, 0.406, 1.002, -0.242, 0.364, -0.323, 0.193, -0.384, -0.14, -0.637, 0.708, -0.121, 0.21, -0.729, -0.402, 0.194, 0.144, -0.109, 0.275, 0.068, -0.822, 0.001}
a3 := []float64{409.16, -503.433, 1085.087, -25.346, -24.641, -29.414, 16.197, 3.018, -2.127, -37.939, 1.918, -3.812, 3.25, -0.096, -0.539, -0.883, 1.558, -2.477, 2.72, -0.914, -0.039, 0.563, -1.438, 1.871, -0.232, -1.257, 0.72, -0.825, 0.262, 0.008, 0.127, 0.142, 0.702, -1.106, 0.614, -0.277, 0.631, -0.799, 0.507, 0.199, -0.414, 0.202, -0.229, 0.172, -0.192, 0.081, -0.165, 0.448, -0.276, 0.11, -0.313, 0.109, 0.199, -0.017, -0.084, 0.128, -0.069, -0.297, 0.274, 0.086}
n := len(y0)
var i int
for i = n - 1; i >= 0; i-- {
if y >= y0[i] {
break
}
}
t := (y - y0[i]) / (y1[i] - y0[i])
dT := a0[i] + t*(a1[i]+t*(a2[i]+t*a3[i]))
return dT
}
func DeltaTv2(jd float64) float64 {
if jd > 2461041.5 || jd < 2441317.5 {
var y float64
if jd >= 2299160.5 {
y = (jd-2451544.5)/365.2425 + 2000
} else {
y = (jd+0.5)/365.25 - 4712
}
return DeltaTSplineY(y)
}
// 闰秒JD值
jdLeaps := []float64{2457754.5, 2457204.5, 2456109.5, 2454832.5,
2453736.5, 2451179.5, 2450630.5, 2450083.5,
2449534.5, 2449169.5, 2448804.5, 2448257.5,
2447892.5, 2447161.5, 2446247.5, 2445516.5,
2445151.5, 2444786.5, 2444239.5, 2443874.5,
2443509.5, 2443144.5, 2442778.5, 2442413.5,
2442048.5, 2441683.5, 2441499.5, 2441133.5}
n := len(jdLeaps)
DT := 42.184
for i := 0; i < n; i++ {
if jd > jdLeaps[i] {
DT += float64(n - i - 1)
break
}
}
return DT
}
func TD2UT(JDE float64, UT2TD bool) float64 { // true 世界时转力学时CCfalse 力学时转世界时VV func TD2UT(JDE float64, UT2TD bool) float64 { // true 世界时转力学时CCfalse 力学时转世界时VV
Deltat := DeltaT(JDE, true) Deltat := DeltaT(JDE, true)
@ -243,93 +330,91 @@ func JDE2DateByZone(JD float64, tz *time.Location, byZone bool) time.Time {
Add(time.Duration(int64(1000000000 * tms))).In(tz) Add(time.Duration(int64(1000000000 * tms))).In(tz)
} }
func GetLunar(year, month, day int, tz float64) (lmonth, lday int, leap bool, result string) { // Date2JDE 日期转儒略日
jde := JDECalc(year, month, float64(day)) //计算当前JDE时间 func Date2JDE(date time.Time) float64 {
if month == 11 || month == 12 { //判断当前日期属于前一年周期还是后一年周期 day := float64(date.Day()) + float64(date.Hour())/24.0 + float64(date.Minute())/24.0/60.0 + float64(date.Second())/24.0/3600.0 + float64(date.Nanosecond())/1000000000.0/3600.0/24.0
//判断方法:当前日期与冬至日所在朔望月的关系 return JDECalc(date.Year(), int(date.Month()), day)
winterday := GetJQTime(year, 270) + tz //冬至日日期(世界时,北京时间) }
Fday := TD2UT(CalcMoonS(float64(year)+11.0/12.0+5.0/30.0/12.0, 0), true) + tz //朔月(世界时,北京时间)
Yday := TD2UT(CalcMoonS(float64(year)+1.0, 0), true) + tz //下一朔月(世界时,北京时间) func GetLunar(year, month, day int, tz float64) (adjustedYear, lmonth, lday int, leap bool, result string) {
if Fday-math.Floor(Fday) > 0.5 { julianDayEpoch := JDECalc(year, month, float64(day))
Fday = math.Floor(Fday) + 0.5 // 确定农历年份
} else { adjustedYear = year
Fday = math.Floor(Fday) - 0.5 if month == 11 || month == 12 {
winterSolsticeDay := GetJQTime(year, 270) + tz
firstNewMoonDay := TD2UT(CalcMoonS(float64(year)+11.0/12.0+5.0/30.0/12.0, 0), true) + tz
nextNewMoonDay := TD2UT(CalcMoonS(float64(year)+1.0, 0), true) + tz
firstNewMoonDay = normalizeTimePoint(firstNewMoonDay)
nextNewMoonDay = normalizeTimePoint(nextNewMoonDay)
if winterSolsticeDay >= firstNewMoonDay && winterSolsticeDay < nextNewMoonDay && julianDayEpoch <= firstNewMoonDay {
adjustedYear--
} }
if Yday-math.Floor(Yday) > 0.5 { if winterSolsticeDay >= nextNewMoonDay && julianDayEpoch < nextNewMoonDay {
Yday = math.Floor(Yday) + 0.5 adjustedYear--
} else {
Yday = math.Floor(Yday) - 0.5
}
if winterday >= Fday && winterday < Yday && jde <= Fday {
year--
}
if winterday >= Yday && jde < Yday {
year--
} }
} else { } else {
year-- adjustedYear--
} }
jieqi := GetJieqiLoops(year, 25) //一年的节气
moon := GetMoonLoops(float64(year), 17) //一年朔月日 // 获取节气和朔望月数据
winter1 := jieqi[0] - 8.0/24 + tz //第一年冬至日 solarTerms := GetJieqiLoops(adjustedYear, 25)
winter2 := jieqi[24] - 8.0/24 + tz //第二年冬至日 newMoonDays := GetMoonLoops(float64(adjustedYear), 17)
for idx, v := range moon {
if tz != 8.0/24 { // 计算冬至日期
v = v - 8.0/24 + tz winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz
} winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz
if v-math.Floor(v) > 0.5 {
moon[idx] = math.Floor(v) + 0.5 // 规范化时间点
} else { normalizeTimeArray(newMoonDays, tz)
moon[idx] = math.Floor(v) - 0.5 normalizeTimeArray(solarTerms, tz)
}
} //置闰月为0点 // 计算朔望月范围
for idx, v := range jieqi { minMoonIndex, maxMoonIndex := 20, 0
if tz != 8.0/24 { moonCount := 0
v = v - 8.0/24 + tz
}
if v-math.Floor(v) > 0.5 {
jieqi[idx] = math.Floor(v) + 0.5
} else {
jieqi[idx] = math.Floor(v) - 0.5
}
} //置节气为0点
mooncount := 0 //年内朔望月计数
var min, max int = 20, 0 //最大最小计数
for i := 0; i < 15; i++ { for i := 0; i < 15; i++ {
if moon[i] >= winter1 && moon[i] < winter2 { if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond {
if i <= min { if i <= minMoonIndex {
min = i minMoonIndex = i
} }
if i >= max { if i >= maxMoonIndex {
max = i maxMoonIndex = i
} }
mooncount++ moonCount++
} }
} }
leapmonth := 20
if mooncount == 13 { //存在闰月 // 确定闰月位置
var j, i = 2, 0 leapMonthPos := 20
for i = min; i <= max; i++ { if moonCount == 13 {
if !(moon[i] <= jieqi[j] && moon[i+1] > jieqi[j]) { solarTermIndex, i := 2, 0
for i = minMoonIndex; i <= maxMoonIndex; i++ {
if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) {
break break
} }
j += 2 solarTermIndex += 2
} }
leapmonth = i - min + 1 leapMonthPos = i - minMoonIndex + 1
} }
i := 0
for i = min - 1; i <= max; i++ { // 找到当前月相索引
if moon[i] > jde { currentMoonIndex := 0
for currentMoonIndex = minMoonIndex - 1; currentMoonIndex <= maxMoonIndex; currentMoonIndex++ {
if newMoonDays[currentMoonIndex] > julianDayEpoch {
break break
} }
} }
lmonth = i - min
var sleap bool = false // 计算农历月份
lmonth = currentMoonIndex - minMoonIndex
shouldAdjustLeap := false
leap = false leap = false
if lmonth >= leapmonth {
sleap = true if lmonth >= leapMonthPos {
shouldAdjustLeap = true
} }
if lmonth == leapmonth { if lmonth == leapMonthPos {
leap = true leap = true
} }
if lmonth < 2 { if lmonth < 2 {
@ -337,102 +422,125 @@ func GetLunar(year, month, day int, tz float64) (lmonth, lday int, leap bool, re
} else { } else {
lmonth-- lmonth--
} }
if sleap { if shouldAdjustLeap {
lmonth-- lmonth--
} }
if lmonth <= 0 { if lmonth <= 0 {
lmonth += 12 lmonth += 12
} }
lday = int(jde-moon[i-1]) + 1
strmonth := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"} // 计算农历日期
strday := []string{"初", "十", "廿", "三"} lday = int(julianDayEpoch-newMoonDays[currentMoonIndex-1]) + 1
if leap {
result += "闰" // 生成农历日期字符串
} result = formatLunarDateString(lmonth, lday, leap)
if lmonth == 1 {
result += "正月"
} else {
result += strmonth[lmonth] + "月"
}
if lday == 20 {
result += "二十"
} else if lday == 10 {
result += "初十"
} else {
result += strday[lday/10] + strmonth[lday%10]
}
return return
} }
func GetSolar(year, month, day int, leap bool, tz float64) float64 { func GetSolar(year, month, day int, leap bool, tz float64) float64 {
adjustedYear := year
if month < 11 { if month < 11 {
year-- adjustedYear--
} }
jieqi := GetJieqiLoops(year, 25) //一年的节气
moon := GetMoonLoops(float64(year), 17) //一年朔月日 // 获取节气和朔望月数据
winter1 := jieqi[0] - 8.0/24 + tz //第一年冬至日 solarTerms := GetJieqiLoops(adjustedYear, 25)
winter2 := jieqi[24] - 8.0/24 + tz //第二年冬至日 newMoonDays := GetMoonLoops(float64(adjustedYear), 17)
for idx, v := range moon {
if tz != 8.0/24 { // 计算冬至日期
v = v - 8.0/24 + tz winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz
} winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz
if v-math.Floor(v) > 0.5 {
moon[idx] = math.Floor(v) + 0.5 // 规范化时间点
} else { normalizeTimeArray(newMoonDays, tz)
moon[idx] = math.Floor(v) - 0.5 normalizeTimeArray(solarTerms, tz)
}
} //置闰月为0点 // 计算朔望月范围
for idx, v := range jieqi { minMoonIndex, maxMoonIndex := 20, 0
if tz != 8.0/24 { moonCount := 0
v = v - 8.0/24 + tz
}
if v-math.Floor(v) > 0.5 {
jieqi[idx] = math.Floor(v) + 0.5
} else {
jieqi[idx] = math.Floor(v) - 0.5
}
} //置节气为0点
mooncount := 0 //年内朔望月计数
var min, max int = 20, 0 //最大最小计数
for i := 0; i < 15; i++ { for i := 0; i < 15; i++ {
if moon[i] >= winter1 && moon[i] < winter2 { if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond {
if i <= min { if i <= minMoonIndex {
min = i minMoonIndex = i
} }
if i >= max { if i >= maxMoonIndex {
max = i maxMoonIndex = i
} }
mooncount++ moonCount++
} }
} }
leapmonth := 20
if mooncount == 13 { //存在闰月 // 确定闰月位置
var j, i = 2, 0 leapMonthPos := 20
for i = min; i <= max; i++ { if moonCount == 13 {
if !(moon[i] <= jieqi[j] && moon[i+1] > jieqi[j]) { solarTermIndex, i := 2, 0
for i = minMoonIndex; i <= maxMoonIndex; i++ {
if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) {
break break
} }
j += 2 solarTermIndex += 2
} }
leapmonth = i - min + 1 leapMonthPos = i - minMoonIndex + 1
} }
// 计算实际月份索引
actualMonth := month
if leap { if leap {
month++ actualMonth++
} }
if month > 10 { if actualMonth > 10 {
month -= 11 actualMonth -= 11
} else { } else {
month++ actualMonth++
} }
if month >= leapmonth && !leap { if actualMonth >= leapMonthPos && !leap {
month++ actualMonth++
} }
jde := moon[min-1+month] + float64(day) - 1
return jde return newMoonDays[minMoonIndex-1+actualMonth] + float64(day) - 1
} }
// Date2JDE 日期转儒略日 func normalizeTimeArray(timeArray []float64, tz float64) {
func Date2JDE(date time.Time) float64 { for idx, timeValue := range timeArray {
day := float64(date.Day()) + float64(date.Hour())/24.0 + float64(date.Minute())/24.0/60.0 + float64(date.Second())/24.0/3600.0 + float64(date.Nanosecond())/1000000000.0/3600.0/24.0 adjustedTime := timeValue
return JDECalc(date.Year(), int(date.Month()), day) if tz != 8.0/24 {
adjustedTime = timeValue - 8.0/24 + tz
}
timeArray[idx] = normalizeTimePoint(adjustedTime)
}
}
func normalizeTimePoint(timePoint float64) float64 {
if timePoint-math.Floor(timePoint) > 0.5 {
return math.Floor(timePoint) + 0.5
}
return math.Floor(timePoint) - 0.5
}
func formatLunarDateString(lunarMonth, lunarDay int, isLeap bool) string {
monthNames := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"}
dayPrefixes := []string{"初", "十", "廿", "三"}
var dateString string
if isLeap {
dateString += "闰"
}
if lunarMonth == 1 {
dateString += "正月"
} else {
dateString += monthNames[lunarMonth] + "月"
}
if lunarDay == 20 {
dateString += "二十"
} else if lunarDay == 10 {
dateString += "初十"
} else {
dateString += dayPrefixes[lunarDay/10] + monthNames[lunarDay%10]
}
return dateString
} }

View File

@ -132,3 +132,88 @@ func magicNumberSpilt(magic int32) (uint16, uint8) {
upper = uint16(magic >> 8) upper = uint16(magic >> 8)
return upper, lower return upper, lower
} }
func TestGetJQTime(t *testing.T) {
originalFunc := func(Year, Angle int) float64 { //节气时间
var j int = 1
var Day int
var tp float64
if Angle%2 == 0 {
Day = 18
} else {
Day = 3
}
if Angle%10 != 0 {
tp = float64(Angle+15.0) / 30.0
} else {
tp = float64(Angle) / 30.0
}
Month := 3 + tp
if Month > 12 {
Month -= 12
}
JD1 := JDECalc(int(Year), int(Month), float64(Day))
if Angle == 0 {
Angle = 360
}
for i := 0; i < j; i++ {
for {
JD0 := JD1
stDegree := JQLospec(JD0, float64(Angle)) - float64(Angle)
stDegreep := (JQLospec(JD0+0.000005, float64(Angle)) - JQLospec(JD0-0.000005, float64(Angle))) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 {
break
}
}
JD1 -= 0.001
}
JD1 += 0.001
return TD2UT(JD1, false)
}
// 测试数据年份从1900-2200抽样角度覆盖关键值
testCases := []struct {
year, angle int
}{
// 边界年份
{1900, 0}, {1900, 15}, {1900, 30}, {1900, 45}, {1900, 90},
{1900, 180}, {1900, 270}, {1900, 360},
// 中间年份抽样
{1950, 0}, {1950, 30}, {1950, 90}, {1950, 180}, {1950, 270},
{2000, 0}, {2000, 15}, {2000, 45}, {2000, 90}, {2000, 360},
{2023, 0}, {2023, 30}, {2023, 90}, {2023, 180}, {2023, 270},
// 未来年份抽样
{2100, 0}, {2100, 15}, {2100, 30}, {2100, 45}, {2100, 90},
{2100, 180}, {2100, 270}, {2100, 360},
{2200, 0}, {2200, 30}, {2200, 90}, {2200, 180}, {2200, 270},
}
// 执行测试
allPassed := true
for _, tc := range testCases {
originalResult := originalFunc(tc.year, tc.angle)
optimizedResult := GetJQTime(tc.year, tc.angle)
diff := math.Abs(originalResult - optimizedResult)
if diff > 1e-10 {
t.Errorf("测试失败: year=%d, angle=%d\n原始结果: %.15f\n优化结果: %.15f\n差异: %.15f",
tc.year, tc.angle, originalResult, optimizedResult, diff)
allPassed = false
} else {
t.Logf("测试通过: year=%d, angle=%d, 结果: %.15f",
tc.year, tc.angle, optimizedResult)
}
}
if allPassed {
t.Log("所有测试用例通过!优化函数与原始函数结果完全一致")
}
}
func TestJQ(t *testing.T) {
fmt.Println(GetJQTime(-721, 15))
}

View File

@ -1430,162 +1430,202 @@ func MoonTimeAngle(JD, Lon, Lat, TZ float64) float64 {
return timeangle return timeangle
} }
func GetMoonRiseTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 { func GetMoonRiseTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 {
ntz := TZ originalTimeZone := timeZone
TZ = Lon / 15 timeZone = longitude / 15
var An, tms float64 = 0, 0 var moonAngle, timeToMeridian float64 = 0, 0
JDZ := math.Floor(JD) + 0.5 julianDayZero := math.Floor(julianDay) + 0.5
JD = math.Floor(JD) + 0.5 - ntz/24 + TZ/24.0 //求0时JDE julianDay = math.Floor(julianDay) + 0.5 - originalTimeZone/24 + timeZone/24 // 求0时JDE
JD1 := JD
moonheight := MoonHeight(JD, Lon, Lat, TZ) //求此时月亮高度
if ZS != 0 {
An = -0.83333 //修正大气折射
}
An = An - HeightDegreeByLat(HEI, Lat)
moonang := MoonTimeAngle(JD, Lon, Lat, TZ)
if moonheight > 0 { //月亮在地平线上或在落下与下中天之间
if moonang > 180 {
tms = (180 + 360 - moonang) / 15
} else {
tms = (180 - moonang) / 15
}
JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0)
estimatedTime := julianDay
moonHeight := MoonHeight(julianDay, longitude, latitude, timeZone) // 求此时月亮高度
if zenithShift != 0 {
moonAngle = -0.83333 // 修正大气折射
} }
if moonheight < 0 && moonang > 180 { moonAngle = moonAngle - HeightDegreeByLat(height, latitude)
tms = (180 - moonang) / 15
JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) moonAngleTime := MoonTimeAngle(julianDay, longitude, latitude, timeZone)
} else if moonheight < 0 && moonang < 180 {
tms = (180 - moonang) / 15 if moonHeight > 0 { // 月亮在地平线上或在落下与下中天之间
JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) if moonAngleTime > 180 {
} timeToMeridian = (180 + 360 - moonAngleTime) / 15
now := MoonTimeAngle(JD1, Lon, Lat, TZ) } else {
if math.Abs(now-180) > 0.5 { timeToMeridian = (180 - moonAngleTime) / 15
JD1 += (180 - now) * 4.0 / 60.0 / 24.0
}
hei := HMoonHeight(JD1, Lon, Lat, TZ)
if !(hei < -10 && math.Abs(Lat) < 60) {
if hei > An {
return -1 //拱
} }
reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0 estimatedTime += (timeToMeridian/24 + (timeToMeridian/24*12.0)/15.0/24.0)
mag := MoonTimeAngle(reJde, Lon, Lat, TZ) }
if mag < 90 {
mag += 360 if moonHeight < 0 && moonAngleTime > 180 {
timeToMeridian = (180 - moonAngleTime) / 15
estimatedTime += (timeToMeridian/24 + (timeToMeridian/24*12.0)/15.0/24.0)
} else if moonHeight < 0 && moonAngleTime < 180 {
timeToMeridian = (180 - moonAngleTime) / 15
estimatedTime += (timeToMeridian/24 + (timeToMeridian/24*12.0)/15.0/24.0)
}
currentAngle := MoonTimeAngle(estimatedTime, longitude, latitude, timeZone)
if math.Abs(currentAngle-180) > 0.5 {
estimatedTime += (180 - currentAngle) * 4.0 / 60.0 / 24.0
}
currentHeight := HMoonHeight(estimatedTime, longitude, latitude, timeZone)
if !(currentHeight < -10 && math.Abs(latitude) < 60) {
if currentHeight > moonAngle {
return -1 // 拱
} }
reJde += (360 - mag) * 4.0 / 60.0 / 24.0 checkTime := estimatedTime + 12.0/24.0 + 6.0/15.0/24.0
if HMoonHeight(reJde, Lon, Lat, TZ) < An { checkAngle := MoonTimeAngle(checkTime, longitude, latitude, timeZone)
return -2 //沉 if checkAngle < 90 {
checkAngle += 360
}
checkTime += (360 - checkAngle) * 4.0 / 60.0 / 24.0
if HMoonHeight(checkTime, longitude, latitude, timeZone) < moonAngle {
return -2 // 沉
} }
} }
dec := MoonApparentDec(JD1, Lon, Lat, TZ)
tmp := (Sin(An) - Sin(dec)*Sin(Lat)) / (Cos(dec) * Cos(Lat)) moonDeclination := MoonApparentDec(estimatedTime, longitude, latitude, timeZone)
if math.Abs(tmp) <= 1 && Lat < 85 { tmp := (Sin(moonAngle) - Sin(moonDeclination)*Sin(latitude)) / (Cos(moonDeclination) * Cos(latitude))
SJ := (180 - ArcCos(tmp)) / 15
JD1 += SJ/24.00 + SJ/33.00/15.00 if math.Abs(tmp) <= 1 && latitude < 85 {
hourAngle := (180 - ArcCos(tmp)) / 15
estimatedTime += hourAngle/24.00 + hourAngle/33.00/15.00
} else { } else {
i := 0 i := 0
for MoonHeight(JD1, Lon, Lat, TZ) < An { for MoonHeight(estimatedTime, longitude, latitude, timeZone) < moonAngle {
i++ i++
JD1 += 15.0 / 60.0 / 24.0 estimatedTime += 15.0 / 60.0 / 24.0
if i > 48 { if i > 48 {
break break
} }
} }
} }
for {
JD0 := JD1
stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An
stDegreep := (HMoonHeight(JD0+0.000005, Lon, Lat, TZ) - HMoonHeight(JD0-0.000005, Lon, Lat, TZ)) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00002 {
break
}
}
JD1 = JD1 - TZ/24 + ntz/24
if JD1 > JDZ+1 || JD1 < JDZ { // 使用牛顿迭代法求精确解
return -3 //明日 estimatedTime = moonRiseSetNewtonRaphsonIteration(estimatedTime, longitude, latitude, timeZone, moonAngle, HMoonHeight, 0.00002)
estimatedTime = estimatedTime - timeZone/24 + originalTimeZone/24
if estimatedTime > julianDayZero+1 || estimatedTime < julianDayZero {
return -3 // 明日
} else { } else {
return JD1 return estimatedTime
} }
} }
func GetMoonDownTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 { func GetMoonSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 {
ntz := TZ originalTimeZone := timeZone
TZ = Lon / 15 timeZone = longitude / 15
var An, tms float64 = 0, 0 var moonAngle, timeToMeridian float64 = 0, 0
JDZ := math.Floor(JD) + 0.5 julianDayZero := math.Floor(julianDay) + 0.5
JD = math.Floor(JD) + 0.5 - ntz/24 + TZ/24 //求0时JDE julianDay = math.Floor(julianDay) + 0.5 - originalTimeZone/24 + timeZone/24 // 求0时JDE
JD1 := JD
moonheight := MoonHeight(JD, Lon, Lat, TZ) //求此时月亮高度 estimatedTime := julianDay
if ZS != 0 { moonHeight := MoonHeight(julianDay, longitude, latitude, timeZone) // 求此时月亮高度
An = -0.83333 //修正大气折射
if zenithShift != 0 {
moonAngle = -0.83333 // 修正大气折射
} }
An = An - HeightDegreeByLat(HEI, Lat) moonAngle = moonAngle - HeightDegreeByLat(height, latitude)
moonang := MoonTimeAngle(JD, Lon, Lat, TZ)
if moonheight < 0 { moonAngleTime := MoonTimeAngle(julianDay, longitude, latitude, timeZone)
tms = (360 - moonang) / 15
JD1 += (tms/24 + (tms/24.0*12.0)/15.0/24.0) if moonHeight < 0 {
timeToMeridian = (360 - moonAngleTime) / 15
estimatedTime += (timeToMeridian/24 + (timeToMeridian/24.0*12.0)/15.0/24.0)
} }
//月亮在地平线上或在落下与下中天之间
if moonheight > 0 && moonang < 180 { // 月亮在地平线上或在落下与下中天之间
tms = (-moonang) / 15 if moonHeight > 0 && moonAngleTime < 180 {
JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0) timeToMeridian = (-moonAngleTime) / 15
} else if moonheight > 0 { estimatedTime += (timeToMeridian/24.0 + (timeToMeridian/24.0*12.0)/15.0/24.0)
tms = (360 - moonang) / 15 } else if moonHeight > 0 {
JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0) timeToMeridian = (360 - moonAngleTime) / 15
estimatedTime += (timeToMeridian/24.0 + (timeToMeridian/24.0*12.0)/15.0/24.0)
} }
now := MoonTimeAngle(JD1, Lon, Lat, TZ)
if now < 180 { currentAngle := MoonTimeAngle(estimatedTime, longitude, latitude, timeZone)
now += 360 if currentAngle < 180 {
currentAngle += 360
} }
if math.Abs(now-360) > 0.5 { if math.Abs(currentAngle-360) > 0.5 {
JD1 += (360 - now) * 4.0 / 60.0 / 24.0 estimatedTime += (360 - currentAngle) * 4.0 / 60.0 / 24.0
} }
//JD1=月球中天时间
hei := HMoonHeight(JD1, Lon, Lat, TZ) // estimatedTime = 月球中天时间
if !(hei > 10 && math.Abs(Lat) < 60) { currentHeight := HMoonHeight(estimatedTime, longitude, latitude, timeZone)
if hei < An { if !(currentHeight > 10 && math.Abs(latitude) < 60) {
return -2 //沉 if currentHeight < moonAngle {
return -2 // 沉
} }
reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0 checkTime := estimatedTime + 12.0/24.0 + 6.0/15.0/24.0
sub := 180 - MoonTimeAngle(reJde, Lon, Lat, TZ) angleSubtraction := 180 - MoonTimeAngle(checkTime, longitude, latitude, timeZone)
reJde += sub * 4.0 / 60.0 / 24.0 checkTime += angleSubtraction * 4.0 / 60.0 / 24.0
if HMoonHeight(reJde, Lon, Lat, TZ) > An { if HMoonHeight(checkTime, longitude, latitude, timeZone) > moonAngle {
return -1 // return -1 //
} }
} }
dec := MoonApparentDec(JD1, Lon, Lat, TZ)
tmp := (Sin(An) - Sin(dec)*Sin(Lat)) / (Cos(dec) * Cos(Lat)) moonDeclination := MoonApparentDec(estimatedTime, longitude, latitude, timeZone)
if math.Abs(tmp) <= 1 && Lat < 85 { tmp := (Sin(moonAngle) - Sin(moonDeclination)*Sin(latitude)) / (Cos(moonDeclination) * Cos(latitude))
SJ := (ArcCos(tmp)) / 15.0
JD1 += SJ/24 + SJ/33.0/15.0 if math.Abs(tmp) <= 1 && latitude < 85 {
hourAngle := (ArcCos(tmp)) / 15.0
estimatedTime += hourAngle/24 + hourAngle/33.0/15.0
} else { } else {
i := 0 i := 0
for MoonHeight(JD1, Lon, Lat, TZ) > An { for MoonHeight(estimatedTime, longitude, latitude, timeZone) > moonAngle {
i++ i++
JD1 += 15.0 / 60.0 / 24.0 estimatedTime += 15.0 / 60.0 / 24.0
if i > 48 { if i > 48 {
break break
} }
} }
} }
// 使用牛顿迭代法求精确解
estimatedTime = moonRiseSetNewtonRaphsonIteration(estimatedTime, longitude, latitude, timeZone, moonAngle, HMoonHeight, 0.00002)
estimatedTime = estimatedTime - timeZone/24 + originalTimeZone/24
if estimatedTime > julianDayZero+1 || estimatedTime < julianDayZero {
return -3 // 明日
} else {
return estimatedTime
}
}
// heightFunction 高度函数类型定义,用于牛顿迭代法
type heightFunction func(time, longitude, latitude, timeZone float64) float64
// moonRiseSetNewtonRaphsonIteration 牛顿-拉夫逊迭代法求解天体高度方程
func moonRiseSetNewtonRaphsonIteration(initialTime, longitude, latitude, timeZone, targetAngle float64,
heightFunc heightFunction, tolerance float64) float64 {
const derivativeStep = 0.000005
currentTime := initialTime
for { for {
JD0 := JD1 previousTime := currentTime
stDegree := HMoonHeight(JD0, Lon, Lat, TZ) - An
stDegreep := (HMoonHeight(JD0+0.000005, Lon, Lat, TZ) - HMoonHeight(JD0-0.000005, Lon, Lat, TZ)) / 0.00001 // 计算函数值f(t) = height(t) - targetAngle
JD1 = JD0 - stDegree/stDegreep functionValue := heightFunc(previousTime, longitude, latitude, timeZone) - targetAngle
if math.Abs(JD1-JD0) <= 0.00002 {
// 计算导数f'(t) ≈ (f(t+h) - f(t-h)) / (2h)
derivative := (heightFunc(previousTime+derivativeStep, longitude, latitude, timeZone) -
heightFunc(previousTime-derivativeStep, longitude, latitude, timeZone)) / (2 * derivativeStep)
// 牛顿-拉夫逊公式t_new = t_old - f(t) / f'(t)
currentTime = previousTime - functionValue/derivative
// 检查收敛
if math.Abs(currentTime-previousTime) <= tolerance {
break break
} }
} }
JD1 = JD1 - TZ/24 + ntz/24
if JD1 > JDZ+1 || JD1 < JDZ { return currentTime
return -3 //明日
} else {
return JD1
}
} }
func GetMoonCir() [][][]float64 { func GetMoonCir() [][][]float64 {

View File

@ -19,7 +19,7 @@ func Benchmark_MoonRiseBench(b *testing.B) {
func Test_MoonDown(t *testing.T) { func Test_MoonDown(t *testing.T) {
jde := GetNowJDE() jde := GetNowJDE()
for i := 30.0; i < 90.0; i += 0.3 { for i := 30.0; i < 90.0; i += 0.3 {
fmt.Println(i, GetMoonDownTime(jde, 115, float64(i), 8, 1, 0)) fmt.Println(i, GetMoonSetTime(jde, 115, float64(i), 8, 1, 0))
} }
} }
func Test_MoonDiff(t *testing.T) { func Test_MoonDiff(t *testing.T) {
@ -100,5 +100,740 @@ func TestMoonCu(t *testing.T) {
//ra, dec := HMoonApparentRaDec(jde, 115, 23, 8) //ra, dec := HMoonApparentRaDec(jde, 115, 23, 8)
//fmt.Println(tools.Format(ra/15, 1), tools.Format(dec, 0)) //fmt.Println(tools.Format(ra/15, 1), tools.Format(dec, 0))
//fmt.Println(JDE2Date(GetMoonTZTime(jde, 115, 23, 8))) //fmt.Println(JDE2Date(GetMoonTZTime(jde, 115, 23, 8)))
//fmt.Println(JDE2Date(GetMoonDownTime(jde+1, 115, 23, 8, 1, 0))) //fmt.Println(JDE2Date(GetMoonSetTime(jde+1, 115, 23, 8, 1, 0)))
}
// MoonRiseSetTestCase 月出月落测试用例
type MoonRiseSetTestCase struct {
Year int
Month int
Day float64
Longitude float64
Latitude float64
TimeZone float64
ZenithShift float64
Height float64
ExpectedRise float64
ExpectedSet float64
}
// moonRiseSetTestData 月出月落测试数据
var moonRiseSetTestData = []MoonRiseSetTestCase{
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 0, 0, 2459959.512382, 2459959.985558},
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 0, 100, 2459959.511766, 2459959.986159},
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 0, 1000, 2459959.510432, 2459959.987458},
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 1, 0, 2459959.509182, 2459959.988676},
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 1, 100, 2459959.508566, 2459959.989275},
{2023, 1, 15.0, 116.4074, 39.9042, 8.0, 1, 1000, 2459959.507235, 2459959.990571},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 0, 0, 2460023.743390, 2460024.191155},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 0, 100, 2460023.742758, 2460024.191788},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460023.741392, 2460024.193155},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 1, 0, 2460023.740112, 2460024.194436},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 1, 100, 2460023.739482, 2460024.195066},
{2023, 3, 20.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460023.738121, 2460024.196429},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 0, 0, 2460116.797325, 2460117.432318},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 0, 100, 2460116.796603, 2460117.433002},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460116.795036, 2460117.434483},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 1, 0, 2460116.793560, 2460117.435878},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 1, 100, 2460116.792831, 2460117.436567},
{2023, 6, 21.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460116.791249, 2460117.438061},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 0, 0, 2460211.101507, 2460211.459840},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 0, 100, 2460211.100724, 2460211.460617},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460211.099038, 2460211.462289},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 1, 0, 2460211.097463, 2460211.463851},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 1, 100, 2460211.096690, 2460211.464618},
{2023, 9, 23.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460211.095023, 2460211.466271},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 0, 0, 2460301.062528, 2460300.594160},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 0, 100, 2460301.061909, 2460300.594781},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460301.060570, 2460300.596125},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 1, 0, 2460301.059311, 2460300.597387},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 1, 100, 2460301.058690, 2460300.598010},
{2023, 12, 22.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460301.057346, 2460300.599358},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 0, 0, 2460370.449673, 2460369.861269},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 0, 100, 2460370.449022, 2460369.861882},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460370.447616, 2460369.863206},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 1, 0, 2460370.446299, 2460369.864446},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 1, 100, 2460370.445651, 2460369.865057},
{2024, 2, 29.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460370.444251, 2460369.866377},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 0, 0, 2460861.080905, 2460860.500448},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 0, 100, 2460861.080262, 2460860.501055},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 0, 1000, 2460861.078875, 2460860.502366},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 1, 0, 2460861.077574, 2460860.503595},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 1, 100, 2460861.076935, 2460860.504200},
{2025, 7, 4.0, 116.4074, 39.9042, 8.0, 1, 1000, 2460861.075553, 2460860.505508},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 0, 0, 2459959.528073, 2459959.967571},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 0, 100, 2459959.527292, 2459959.968329},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 0, 1000, 2459959.525607, 2459959.969964},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 1, 0, 2459959.524029, 2459959.971495},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 1, 100, 2459959.523252, 2459959.972249},
{2023, 1, 15.0, -0.1276, 51.5074, 0.0, 1, 1000, 2459959.521574, 2459959.973876},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 0, 0, 2460023.756367, 2460024.186083},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 0, 100, 2460023.755588, 2460024.186873},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460023.753909, 2460024.188577},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 1, 0, 2460023.752338, 2460024.190171},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 1, 100, 2460023.751564, 2460024.190956},
{2023, 3, 20.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460023.749895, 2460024.192651},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 0, 0, 2460116.767473, 2460117.458902},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 0, 100, 2460116.766492, 2460117.459792},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460116.764358, 2460117.461726},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 1, 0, 2460116.762340, 2460117.463551},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 1, 100, 2460116.761338, 2460117.464456},
{2023, 6, 21.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460116.759156, 2460117.466421},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 0, 0, 2460211.152489, 2460211.418569},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 0, 100, 2460211.151311, 2460211.419741},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460211.148791, 2460211.422249},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 1, 0, 2460211.146459, 2460211.424570},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 1, 100, 2460211.145319, 2460211.425704},
{2023, 9, 23.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460211.142878, 2460211.428132},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 0, 0, 2460301.041592, 2460300.614867},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 0, 100, 2460301.040804, 2460300.615663},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460301.039097, 2460300.617388},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 1, 0, 2460301.037491, 2460300.619011},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 1, 100, 2460301.036696, 2460300.619812},
{2023, 12, 22.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460301.034975, 2460300.621551},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 0, 0, 2460370.477943, 2460369.838418},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 0, 100, 2460370.477078, 2460369.839203},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460370.475212, 2460369.840897},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 1, 0, 2460370.473471, 2460369.842481},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 1, 100, 2460370.472615, 2460369.843260},
{2024, 2, 29.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460370.470771, 2460369.844941},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 0, 0, 2460861.106361, 2460861.487905},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 0, 100, 2460861.105517, 2460861.488735},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 0, 1000, 2460861.103697, 2460861.490524},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 1, 0, 2460861.101998, 2460861.492193},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 1, 100, 2460861.101162, 2460861.493015},
{2025, 7, 4.0, -0.1276, 51.5074, 0.0, 1, 1000, 2460861.099360, 2460861.494784},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 0, 0, 2459959.524199, 2459959.980835},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 0, 100, 2459959.523565, 2459959.981455},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 0, 1000, 2459959.522195, 2459959.982795},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 1, 0, 2459959.520911, 2459959.984050},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 1, 100, 2459959.520279, 2459959.984669},
{2023, 1, 15.0, -74.0060, 40.7128, -5.0, 1, 1000, 2459959.518912, 2459959.986004},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 0, 0, 2460023.742085, 2460024.205917},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 0, 100, 2460023.741461, 2460024.206545},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460023.740113, 2460024.207902},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 1, 0, 2460023.738849, 2460024.209175},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 1, 100, 2460023.738227, 2460024.209801},
{2023, 3, 20.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460023.736882, 2460024.211155},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 0, 0, 2460116.805442, 2460117.432629},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 0, 100, 2460116.804724, 2460117.433304},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460116.803169, 2460117.434767},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 1, 0, 2460116.801705, 2460117.436144},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 1, 100, 2460116.800981, 2460117.436824},
{2023, 6, 21.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460116.799411, 2460117.438298},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 0, 0, 2460211.112450, 2460211.469949},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 0, 100, 2460211.111661, 2460211.470732},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460211.109960, 2460211.472418},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 1, 0, 2460211.108372, 2460211.473992},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 1, 100, 2460211.107592, 2460211.474766},
{2023, 9, 23.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460211.105912, 2460211.476431},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 0, 0, 2460301.058738, 2460300.608360},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 0, 100, 2460301.058096, 2460300.609002},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460301.056706, 2460300.610392},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 1, 0, 2460301.055399, 2460300.611699},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 1, 100, 2460301.054753, 2460300.612344},
{2023, 12, 22.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460301.053356, 2460300.613740},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 0, 0, 2460370.461773, 2460369.855646},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 0, 100, 2460370.461094, 2460369.856281},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460370.459628, 2460369.857653},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 1, 0, 2460370.458256, 2460369.858938},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 1, 100, 2460370.457581, 2460369.859571},
{2024, 2, 29.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460370.456124, 2460369.860937},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 0, 0, 2460861.092013, -3.000000},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 0, 100, 2460861.091345, -3.000000},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 0, 1000, 2460861.089903, -3.000000},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 1, 0, 2460861.088553, -3.000000},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 1, 100, 2460861.087889, -3.000000},
{2025, 7, 4.0, -74.0060, 40.7128, -5.0, 1, 1000, 2460861.086455, -3.000000},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 0, 0, 2459960.490771, 2459960.006541},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 0, 100, 2459960.490206, 2459960.007105},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 0, 1000, 2459960.488984, 2459960.008325},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 1, 0, 2459960.487836, 2459960.009472},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 1, 100, 2459960.487270, 2459960.010038},
{2023, 1, 15.0, 151.2093, -33.8688, 10.0, 1, 1000, 2459960.486046, 2459960.011261},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 0, 0, 2460023.660650, 2460024.225595},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 0, 100, 2460023.660054, 2460024.226157},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460023.658765, 2460024.227373},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 1, 0, 2460023.657552, 2460024.228516},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 1, 100, 2460023.656954, 2460024.229079},
{2023, 3, 20.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460023.655660, 2460024.230298},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 0, 0, 2460116.898383, 2460117.306845},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 0, 100, 2460116.897736, 2460117.307485},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460116.896339, 2460117.308867},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 1, 0, 2460116.895031, 2460117.310161},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 1, 100, 2460116.894388, 2460117.310797},
{2023, 6, 21.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460116.892999, 2460117.312170},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 0, 0, 2460210.944935, 2460210.538063},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 0, 100, 2460210.944257, 2460210.538734},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460210.942787, 2460210.540189},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 1, 0, 2460210.941402, 2460210.541559},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 1, 100, 2460210.940719, 2460210.542236},
{2023, 9, 23.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460210.939236, 2460210.543703},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 0, 0, 2460301.101438, 2460300.536189},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 0, 100, 2460301.100851, 2460300.536745},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460301.099584, 2460300.537947},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 1, 0, 2460301.098395, 2460300.539074},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 1, 100, 2460301.097810, 2460300.539629},
{2023, 12, 22.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460301.096546, 2460300.540829},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 0, 0, 2460370.367522, 2460369.898187},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 0, 100, 2460370.366947, 2460369.898759},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460370.365705, 2460369.899996},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 1, 0, 2460370.364537, 2460369.901160},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 1, 100, 2460370.363961, 2460369.901733},
{2024, 2, 29.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460370.362714, 2460369.902974},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 0, 0, 2460861.005584, 2460860.530894},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 0, 100, 2460861.005015, 2460860.531462},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 0, 1000, 2460861.003784, 2460860.532690},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 1, 0, 2460861.002627, 2460860.533844},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 1, 100, 2460861.002057, 2460860.534413},
{2025, 7, 4.0, 151.2093, -33.8688, 10.0, 1, 1000, 2460861.000823, 2460860.535644},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 0, 0, -3.000000, 2459959.964633},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 0, 100, -3.000000, 2459959.965199},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 0, 1000, -3.000000, 2459959.966422},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 1, 0, -3.000000, 2459959.967570},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 1, 100, -3.000000, 2459959.968135},
{2023, 1, 15.0, 139.6503, 35.6762, 9.0, 1, 1000, -3.000000, 2459959.969356},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 0, 0, 2460023.713764, 2460024.169244},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 0, 100, 2460023.713167, 2460024.169838},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460023.711878, 2460024.171123},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 1, 0, 2460023.710670, 2460024.172328},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 1, 100, 2460023.710075, 2460024.172921},
{2023, 3, 20.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460023.708791, 2460024.174202},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 0, 0, 2460116.781251, 2460117.399403},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 0, 100, 2460116.780582, 2460117.400040},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460116.779133, 2460117.401421},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 1, 0, 2460116.777769, 2460117.402720},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 1, 100, 2460116.777095, 2460117.403362},
{2023, 6, 21.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460116.775635, 2460117.404751},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 0, 0, 2460211.063872, 2460211.445971},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 0, 100, 2460211.063158, 2460211.446679},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460211.061618, 2460211.448205},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 1, 0, 2460211.060178, 2460211.449632},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 1, 100, 2460211.059470, 2460211.450334},
{2023, 9, 23.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460211.057944, 2460211.451846},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 0, 0, 2460301.042488, 2460300.564993},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 0, 100, 2460301.041906, 2460300.565575},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460301.040647, 2460300.566835},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 1, 0, 2460301.039464, 2460300.568019},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 1, 100, 2460301.038880, 2460300.568603},
{2023, 12, 22.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460301.037617, 2460300.569866},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 0, 0, 2460370.418418, 2460369.841663},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 0, 100, 2460370.417811, 2460369.842239},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460370.416500, 2460369.843482},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 1, 0, 2460370.415270, 2460369.844648},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 1, 100, 2460370.414665, 2460369.845222},
{2024, 2, 29.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460370.413358, 2460369.846462},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 0, 0, 2460861.050307, 2460861.497476},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 0, 100, 2460861.049707, 2460861.498067},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 0, 1000, 2460861.048410, 2460861.499345},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 1, 0, 2460861.047194, -3.000000},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 1, 100, 2460861.046596, -3.000000},
{2025, 7, 4.0, 139.6503, 35.6762, 9.0, 1, 1000, 2460861.045303, -3.000000},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 0, 0, 2459959.559564, 2459960.005972},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 0, 100, 2459959.558830, 2459960.006686},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 0, 1000, 2459959.557244, 2459960.008228},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 1, 0, 2459959.555759, 2459960.009670},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 1, 100, 2459959.555028, 2459960.010381},
{2023, 1, 15.0, 2.3522, 48.8566, 1.0, 1, 1000, 2459959.553448, 2459960.011915},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 0, 0, 2460023.786730, 2460024.223914},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 0, 100, 2460023.785997, 2460024.224655},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 0, 1000, 2460023.784414, 2460024.226257},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 1, 0, 2460023.782934, 2460024.227755},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 1, 100, 2460023.782205, 2460024.228493},
{2023, 3, 20.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460023.780631, 2460024.230087},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 0, 0, 2460116.811447, 2460117.485600},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 0, 100, 2460116.810552, 2460117.486423},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 0, 1000, 2460116.808608, 2460117.488210},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 1, 0, 2460116.806771, 2460117.489894},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 1, 100, 2460116.805861, 2460117.490728},
{2023, 6, 21.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460116.803882, 2460117.492539},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 0, 0, 2460211.173246, 2460211.466625},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 0, 100, 2460211.172210, 2460211.467656},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 0, 1000, 2460211.169986, 2460211.469867},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 1, 0, 2460211.167921, 2460211.471920},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 1, 100, 2460211.166909, 2460211.472925},
{2023, 9, 23.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460211.164738, 2460211.475084},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 0, 0, 2460301.080943, 2460300.645364},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 0, 100, 2460301.080203, 2460300.646110},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 0, 1000, 2460301.078599, 2460300.647728},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 1, 0, 2460301.077090, 2460300.649248},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 1, 100, 2460301.076345, 2460300.649999},
{2023, 12, 22.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460301.074729, 2460300.651627},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 0, 0, -3.000000, 2460369.878053},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 0, 100, -3.000000, 2460369.878790},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 0, 1000, -3.000000, 2460369.880379},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 1, 0, -3.000000, 2460369.881866},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 1, 100, -3.000000, 2460369.882598},
{2024, 2, 29.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460370.499203, 2460369.884177},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 0, 0, 2460861.134958, 2460860.518461},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 0, 100, 2460861.134172, 2460860.519186},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 0, 1000, 2460861.132477, 2460860.520751},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 1, 0, 2460861.130892, 2460860.522216},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 1, 100, 2460861.130113, 2460860.522937},
{2025, 7, 4.0, 2.3522, 48.8566, 1.0, 1, 1000, 2460861.128432, 2460860.524494},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 0, 0, 2459959.522069, 2459959.987849},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 0, 100, 2459959.521491, 2459959.988416},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 0, 1000, 2459959.520242, 2459959.989642},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 1, 0, 2459959.519071, 2459959.990791},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 1, 100, 2459959.518495, 2459959.991357},
{2023, 1, 15.0, -118.2437, 34.0522, -8.0, 1, 1000, 2459959.517249, 2459959.992580},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 0, 0, 2460023.736567, 2460024.214432},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 0, 100, 2460023.736000, 2460024.215000},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460023.734774, 2460024.216228},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 1, 0, 2460023.733624, 2460024.217380},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 1, 100, 2460023.733057, 2460024.217947},
{2023, 3, 20.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460023.731834, 2460024.219174},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 0, 0, 2460116.821912, 2460117.421511},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 0, 100, 2460116.821278, 2460117.422113},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460116.819905, 2460117.423419},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 1, 0, 2460116.818612, 2460117.424647},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 1, 100, 2460116.817974, 2460117.425253},
{2023, 6, 21.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460116.816593, 2460117.426565},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 0, 0, 2460211.096832, 2460211.491736},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 0, 100, 2460211.096147, 2460211.492414},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460211.094671, 2460211.493874},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 1, 0, 2460211.093289, 2460211.495241},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 1, 100, 2460211.092609, 2460211.495913},
{2023, 9, 23.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460211.091144, 2460211.497363},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 0, 0, 2460301.067741, 2460300.604932},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 0, 100, 2460301.067155, 2460300.605516},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460301.065885, 2460300.606778},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 1, 0, 2460301.064690, 2460300.607966},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 1, 100, 2460301.064101, 2460300.608551},
{2023, 12, 22.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460301.062827, 2460300.609819},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 0, 0, 2460370.454262, 2460369.864349},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 0, 100, 2460370.453650, 2460369.864928},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460370.452328, 2460369.866178},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 1, 0, 2460370.451090, 2460369.867351},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 1, 100, 2460370.450481, 2460369.867928},
{2024, 2, 29.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460370.449165, 2460369.869174},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 0, 0, 2460861.085220, 2460860.502309},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 0, 100, 2460861.084616, 2460860.502881},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 0, 1000, 2460861.083313, 2460860.504118},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 1, 0, 2460861.082092, 2460860.505277},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 1, 100, 2460861.081491, 2460860.505848},
{2025, 7, 4.0, -118.2437, 34.0522, -8.0, 1, 1000, 2460861.080193, 2460860.507081},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 0, 0, 2459959.547825, 2459959.980183},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 0, 100, 2459959.546956, 2459959.981023},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 0, 1000, 2459959.545083, 2459959.982834},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 1, 0, 2459959.543330, 2459959.984528},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 1, 100, 2459959.542467, 2459959.985362},
{2023, 1, 15.0, 37.6176, 55.7558, 3.0, 1, 1000, 2459959.540603, 2459959.987162},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 0, 0, 2460023.783999, 2460024.192547},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 0, 100, 2460023.783120, 2460024.193442},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 0, 1000, 2460023.781224, 2460024.195371},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 1, 0, 2460023.779453, 2460024.197173},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 1, 100, 2460023.778582, 2460024.198060},
{2023, 3, 20.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460023.776703, 2460024.199974},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 0, 0, 2460116.763078, 2460117.493338},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 0, 100, 2460116.761877, 2460117.494391},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 0, 1000, 2460116.759256, 2460117.496682},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 1, 0, 2460116.756765, 2460117.498850},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 1, 100, 2460116.755522, 2460117.499928},
{2023, 6, 21.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460116.752806, -3.000000},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 0, 0, 2460211.198496, 2460211.403741},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 0, 100, 2460211.196886, 2460211.405346},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 0, 1000, 2460211.193474, 2460211.408746},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 1, 0, 2460211.190358, 2460211.411852},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 1, 100, 2460211.188847, 2460211.413357},
{2023, 9, 23.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460211.185637, 2460211.416556},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 0, 0, 2460301.052264, 2460300.635877},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 0, 100, 2460301.051388, 2460300.636766},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 0, 1000, 2460301.049490, 2460300.638694},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 1, 0, 2460301.047704, 2460300.640507},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 1, 100, 2460301.046819, 2460300.641404},
{2023, 12, 22.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460301.044901, 2460300.643350},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 0, 0, -3.000000, 2460369.848787},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 0, 100, -3.000000, 2460369.849664},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 0, 1000, -3.000000, 2460369.851553},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 1, 0, 2460370.499620, 2460369.853318},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 1, 100, 2460370.498648, 2460369.854186},
{2024, 2, 29.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460370.496557, 2460369.856057},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 0, 0, 2460861.132034, 2460861.495198},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 0, 100, 2460861.131078, 2460861.496137},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 0, 1000, 2460861.129018, 2460861.498158},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 1, 0, 2460861.127098, -3.000000},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 1, 100, 2460861.126154, -3.000000},
{2025, 7, 4.0, 37.6176, 55.7558, 3.0, 1, 1000, 2460861.124122, -3.000000},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 0, 0, 2459959.503589, 2459959.983951},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 0, 100, 2459959.503044, 2459959.984486},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 0, 1000, 2459959.501865, 2459959.985642},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 1, 0, 2459959.500758, 2459959.986727},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 1, 100, 2459959.500214, 2459959.987262},
{2023, 1, 15.0, 31.2357, 30.0444, 2.0, 1, 1000, -3.000000, 2459959.988416},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 0, 0, 2460023.724714, 2460024.198340},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 0, 100, 2460023.724163, 2460024.198888},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460023.722973, 2460024.200072},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 1, 0, 2460023.721856, 2460024.201183},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 1, 100, 2460023.721307, 2460024.201730},
{2023, 3, 20.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460023.720119, 2460024.202912},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 0, 0, 2460116.813768, 2460117.406719},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 0, 100, 2460116.813160, 2460117.407301},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460116.811843, 2460117.408562},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 1, 0, 2460116.810603, 2460117.409748},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 1, 100, 2460116.809991, 2460117.410333},
{2023, 6, 21.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460116.808667, 2460117.411600},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 0, 0, 2460211.072262, 2460211.482710},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 0, 100, 2460211.071615, 2460211.483350},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460211.070218, 2460211.484732},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 1, 0, 2460211.068910, 2460211.486026},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 1, 100, 2460211.068266, 2460211.486662},
{2023, 9, 23.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460211.066878, 2460211.488035},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 0, 0, 2460301.063789, 2460300.584090},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 0, 100, 2460301.063237, 2460300.584638},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460301.062045, 2460300.585823},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 1, 0, 2460301.060923, 2460300.586938},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 1, 100, 2460301.060371, 2460300.587487},
{2023, 12, 22.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460301.059175, 2460300.588676},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 0, 0, 2460370.433373, 2460369.862017},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 0, 100, 2460370.432803, 2460369.862561},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460370.431570, 2460369.863735},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 1, 0, 2460370.430414, 2460369.864837},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 1, 100, 2460370.429845, 2460369.865380},
{2024, 2, 29.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460370.428616, 2460369.866552},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 0, 0, 2460861.065509, -3.000000},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 0, 100, 2460861.064944, -3.000000},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 0, 1000, 2460861.063725, -3.000000},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 1, 0, 2460861.062582, -3.000000},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 1, 100, 2460861.062019, -3.000000},
{2025, 7, 4.0, 31.2357, 30.0444, 2.0, 1, 1000, 2460861.060803, -3.000000},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 0, 0, -3.000000, 2459960.019905},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 0, 100, -3.000000, 2459960.020416},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 0, 1000, -3.000000, 2459960.021522},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 1, 0, -3.000000, 2459960.022561},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 1, 100, -3.000000, 2459960.023073},
{2023, 1, 15.0, -43.1729, -22.9068, -3.0, 1, 1000, -3.000000, 2459960.024180},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 0, 0, 2460023.694314, 2460024.230676},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 0, 100, 2460023.693794, 2460024.231175},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460023.692668, 2460024.232255},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 1, 0, 2460023.691609, 2460024.233270},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 1, 100, 2460023.691087, 2460024.233769},
{2023, 3, 20.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460023.689959, 2460024.234850},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 0, 0, 2460116.892241, 2460117.344631},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 0, 100, 2460116.891685, 2460117.345179},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460116.890485, 2460117.346361},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 1, 0, 2460116.889358, 2460117.347471},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 1, 100, 2460116.888804, 2460117.348016},
{2023, 6, 21.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460116.887607, 2460117.349195},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 0, 0, 2460210.989126, 2460210.536957},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 0, 100, 2460210.988538, 2460210.537539},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460210.987264, 2460210.538800},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 1, 0, 2460210.986066, 2460210.539987},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 1, 100, 2460210.985475, 2460210.540571},
{2023, 9, 23.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460210.984195, 2460210.541838},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 0, 0, 2460301.112646, 2460300.554998},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 0, 100, 2460301.112115, 2460300.555506},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460301.110966, 2460300.556605},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 1, 0, 2460301.109888, 2460300.557636},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 1, 100, 2460301.109358, 2460300.558144},
{2023, 12, 22.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460301.108212, 2460300.559241},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 0, 0, 2460370.388602, 2460369.907565},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 0, 100, 2460370.388077, 2460369.908083},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460370.386942, 2460369.909204},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 1, 0, 2460370.385874, 2460369.910257},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 1, 100, 2460370.385348, 2460369.910776},
{2024, 2, 29.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460370.384210, 2460369.911899},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 0, 0, 2460861.024935, 2460860.540907},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 0, 100, 2460861.024416, 2460860.541421},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 0, 1000, 2460861.023292, 2460860.542532},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 1, 0, 2460861.022235, 2460860.543577},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 1, 100, 2460861.021714, 2460860.544092},
{2025, 7, 4.0, -43.1729, -22.9068, -3.0, 1, 1000, 2460861.020587, 2460860.545205},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 0, 0, 2459959.533659, 2459960.042803},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 0, 100, 2459959.533195, 2459960.043265},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 0, 1000, 2459959.532189, 2459960.044264},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 1, 0, 2459959.531245, 2459960.045203},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 1, 100, 2459959.530780, 2459960.045665},
{2023, 1, 15.0, 103.8198, 1.3521, 8.0, 1, 1000, 2459959.529774, 2459960.046664},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 0, 0, 2460023.744413, 2460024.255583},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 0, 100, 2460023.743933, 2460024.256050},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460023.742895, 2460024.257061},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 1, 0, 2460023.741919, 2460024.258011},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 1, 100, 2460023.741439, 2460024.258479},
{2023, 3, 20.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460023.740401, 2460024.259490},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 0, 0, 2460116.896343, 2460117.411271},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 0, 100, 2460116.895833, 2460117.411769},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460116.894729, 2460117.412845},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 1, 0, 2460116.893692, 2460117.413857},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 1, 100, 2460116.893181, 2460117.414355},
{2023, 6, 21.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460116.892077, 2460117.415431},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 0, 0, 2460211.061198, 2460210.530116},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 0, 100, 2460211.060667, 2460210.530639},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460211.059519, 2460210.531771},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 1, 0, 2460211.058440, 2460210.532834},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 1, 100, 2460211.057909, 2460210.533357},
{2023, 9, 23.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460211.056761, 2460210.534489},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 0, 0, 2460301.128082, 2460300.607764},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 0, 100, 2460301.127606, 2460300.608229},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460301.126577, 2460300.609234},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 1, 0, 2460301.125610, 2460300.610178},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 1, 100, 2460301.125133, 2460300.610643},
{2023, 12, 22.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460301.124104, 2460300.611648},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 0, 0, 2460370.448355, 2460369.926847},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 0, 100, 2460370.447876, 2460369.927314},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460370.446841, 2460369.928323},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 1, 0, 2460370.445868, 2460369.929271},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 1, 100, 2460370.445389, 2460369.929738},
{2024, 2, 29.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460370.444354, 2460369.930747},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 0, 0, 2460861.083263, 2460860.562492},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 0, 100, 2460861.082788, 2460860.562956},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 0, 1000, 2460861.081761, 2460860.563959},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 1, 0, 2460861.080795, 2460860.564902},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 1, 100, 2460861.080320, 2460860.565366},
{2025, 7, 4.0, 103.8198, 1.3521, 8.0, 1, 1000, 2460861.079293, 2460860.566370},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 0, 0, 2459959.611424, 2459959.989333},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 0, 100, 2459959.610339, 2459959.990387},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 0, 1000, 2459959.608002, 2459959.992654},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 1, 0, 2459959.605825, 2459959.994766},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 1, 100, 2459959.604754, 2459959.995804},
{2023, 1, 15.0, -149.9003, 61.2181, -9.0, 1, 1000, 2459959.602447, 2459959.998039},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 0, 0, 2460023.818593, 2460024.240506},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 0, 100, 2460023.817597, 2460024.241534},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460023.815451, 2460024.243752},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 1, 0, 2460023.813448, 2460024.245824},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 1, 100, 2460023.812461, 2460024.246844},
{2023, 3, 20.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460023.810334, 2460024.249046},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 0, 0, 2460116.779694, 2460116.541691},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 0, 100, 2460116.778105, 2460116.543268},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460116.774605, 2460116.546739},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 1, 0, 2460116.771242, 2460116.550076},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 1, 100, 2460116.769551, 2460116.551755},
{2023, 6, 21.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460116.765815, 2460116.555463},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 0, 0, 2460211.309271, 2460211.381831},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 0, 100, 2460211.304548, 2460211.386551},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460211.295817, 2460211.395275},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 1, 0, 2460211.288811, 2460211.402275},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 1, 100, 2460211.285643, 2460211.405440},
{2023, 9, 23.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460211.279287, 2460211.411788},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 0, 0, 2460301.058819, 2460300.705421},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 0, 100, 2460301.057690, 2460300.706565},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460301.055234, 2460300.709054},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 1, 0, 2460301.052913, 2460300.711406},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 1, 100, 2460301.051759, 2460300.712574},
{2023, 12, 22.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460301.049249, 2460300.715116},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 0, 0, 2460369.515897, 2460369.852889},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 0, 100, 2460369.514732, 2460369.854028},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460369.512230, 2460369.856476},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 1, 0, 2460369.509904, 2460369.858750},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 1, 100, 2460369.508763, 2460369.859866},
{2024, 2, 29.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460369.506308, 2460369.862264},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 0, 0, 2460861.205484, 2460861.493716},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 0, 100, 2460861.204170, 2460861.495011},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 0, 1000, 2460861.201358, 2460861.497780},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 1, 0, 2460861.198757, -3.000000},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 1, 100, 2460861.197484, -3.000000},
{2025, 7, 4.0, -149.9003, 61.2181, -9.0, 1, 1000, 2460861.194755, -3.000000},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 0, 0, 2459959.583014, 2459959.895953},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 0, 100, 2459959.581157, 2459959.897741},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 0, 1000, 2459959.577188, 2459959.901560},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 1, 0, 2459959.573523, 2459959.905081},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 1, 100, 2459959.571731, 2459959.906801},
{2023, 1, 15.0, -42.6043, 71.7069, -3.0, 1, 1000, 2459959.567893, 2459959.910481},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 0, 0, 2460023.817806, 2460024.130940},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 0, 100, 2460023.816003, 2460024.132810},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 0, 1000, 2460023.812151, 2460024.136808},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 1, 0, 2460023.808601, 2460024.140499},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 1, 100, 2460023.806866, 2460024.142304},
{2023, 3, 20.0, -42.6043, 71.7069, -3.0, 1, 1000, 2460023.803156, 2460024.146170},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 0, 0, -1.000000, -1.000000},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 0, 100, -1.000000, -1.000000},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 0, 1000, -1.000000, -1.000000},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 1, 0, -1.000000, -1.000000},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 1, 100, -1.000000, -1.000000},
{2023, 6, 21.0, -42.6043, 71.7069, -3.0, 1, 1000, -1.000000, -1.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 0, 0, -2.000000, -2.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 0, 100, -2.000000, -2.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 0, 1000, -2.000000, -2.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 1, 0, -2.000000, -2.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 1, 100, -2.000000, -2.000000},
{2023, 9, 23.0, -42.6043, 71.7069, -3.0, 1, 1000, -2.000000, -2.000000},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 0, 0, 2460300.951391, 2460300.689493},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 0, 100, 2460300.949276, 2460300.691656},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 0, 1000, 2460300.944604, 2460300.696431},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 1, 0, 2460300.940091, 2460300.701037},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 1, 100, 2460300.937809, 2460300.703365},
{2023, 12, 22.0, -42.6043, 71.7069, -3.0, 1, 1000, 2460300.932741, 2460300.708530},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 0, 0, 2460369.510257, 2460369.739050},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 0, 100, 2460369.507908, 2460369.741347},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 0, 1000, 2460369.502952, 2460369.746190},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 1, 0, -3.000000, 2460369.750583},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 1, 100, -3.000000, 2460369.752708},
{2024, 2, 29.0, -42.6043, 71.7069, -3.0, 1, 1000, -3.000000, 2460369.757206},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 0, 0, 2460861.253176, 2460861.327087},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 0, 100, 2460861.246829, 2460861.333396},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 0, 1000, 2460861.235509, 2460861.344631},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 1, 0, 2460861.226647, 2460861.353412},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 1, 100, 2460861.222676, 2460861.357343},
{2025, 7, 4.0, -42.6043, 71.7069, -3.0, 1, 1000, 2460861.214758, 2460861.365173},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 0, 0, -1.000000, -1.000000},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 0, 100, -1.000000, -1.000000},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 0, 1000, -1.000000, -1.000000},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 1, 0, -1.000000, -1.000000},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 1, 100, -1.000000, -1.000000},
{2023, 1, 15.0, 0.0000, -85.0000, 0.0, 1, 1000, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 0, 0, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 0, 100, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 0, 1000, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 1, 0, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 1, 100, -1.000000, -1.000000},
{2023, 3, 20.0, 0.0000, -85.0000, 0.0, 1, 1000, -1.000000, -1.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 0, 0, -2.000000, -2.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 0, 100, -2.000000, -2.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 0, 1000, -2.000000, -2.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 1, 0, -2.000000, -2.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 1, 100, -2.000000, -2.000000},
{2023, 6, 21.0, 0.0000, -85.0000, 0.0, 1, 1000, -2.000000, -2.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 0, 0, -1.000000, -1.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 0, 100, -1.000000, -1.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 0, 1000, -1.000000, -1.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 1, 0, -1.000000, -1.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 1, 100, -1.000000, -1.000000},
{2023, 9, 23.0, 0.0000, -85.0000, 0.0, 1, 1000, -1.000000, -1.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 0, 0, -2.000000, -2.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 0, 100, -2.000000, -2.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 0, 1000, -2.000000, -2.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 1, 0, -2.000000, -2.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 1, 100, -2.000000, -2.000000},
{2023, 12, 22.0, 0.0000, -85.0000, 0.0, 1, 1000, -2.000000, -2.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 0, 0, -1.000000, -1.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 0, 100, -1.000000, -1.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 0, 1000, -1.000000, -1.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 1, 0, -1.000000, -1.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 1, 100, -1.000000, -1.000000},
{2024, 2, 29.0, 0.0000, -85.0000, 0.0, 1, 1000, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 0, 0, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 0, 100, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 0, 1000, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 1, 0, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 1, 100, -1.000000, -1.000000},
{2025, 7, 4.0, 0.0000, -85.0000, 0.0, 1, 1000, -1.000000, -1.000000},
}
// TestMoonRiseSetRegression 月出月落回归测试
func TestMoonRiseSetRegression(t *testing.T) {
beforeDeltaT := defDeltaTFn
SetDeltaTFn(DefaultDeltaT)
defer SetDeltaTFn(beforeDeltaT)
const tolerance = 0.000001 // 容差设为1微秒对于天文计算来说已经足够精确
for i, testCase := range moonRiseSetTestData {
julianDay := JDECalc(testCase.Year, testCase.Month, testCase.Day)
// 测试月出时间
actualRise := GetMoonRiseTime(julianDay, testCase.Longitude, testCase.Latitude,
testCase.TimeZone, testCase.ZenithShift, testCase.Height)
if !floatEquals(actualRise, testCase.ExpectedRise, tolerance) {
t.Errorf("测试用例 %d 月出时间不匹配:\n"+
" 日期: %d-%d-%.1f, 经纬度: (%.4f, %.4f), 时区: %.1f, 天顶修正: %.0f, 海拔: %.0f\n"+
" 期望月出: %.6f, 实际月出: %.6f, 差值: %.9f",
i, testCase.Year, testCase.Month, testCase.Day,
testCase.Longitude, testCase.Latitude, testCase.TimeZone,
testCase.ZenithShift, testCase.Height,
testCase.ExpectedRise, actualRise, math.Abs(actualRise-testCase.ExpectedRise))
}
// 测试月落时间
actualSet := GetMoonSetTime(julianDay, testCase.Longitude, testCase.Latitude,
testCase.TimeZone, testCase.ZenithShift, testCase.Height)
if !floatEquals(actualSet, testCase.ExpectedSet, tolerance) {
t.Errorf("测试用例 %d 月落时间不匹配:\n"+
" 日期: %d-%d-%.1f, 经纬度: (%.4f, %.4f), 时区: %.1f, 天顶修正: %.0f, 海拔: %.0f\n"+
" 期望月落: %.6f, 实际月落: %.6f, 差值: %.9f",
i, testCase.Year, testCase.Month, testCase.Day,
testCase.Longitude, testCase.Latitude, testCase.TimeZone,
testCase.ZenithShift, testCase.Height,
testCase.ExpectedSet, actualSet, math.Abs(actualSet-testCase.ExpectedSet))
}
}
t.Logf("月出月落回归测试通过,共测试 %d 个用例", len(moonRiseSetTestData))
}
// TestMoonRiseSetSpecialCases 测试特殊情况
func TestMoonRiseSetSpecialCases(t *testing.T) {
beforeDeltaT := defDeltaTFn
SetDeltaTFn(DefaultDeltaT)
defer SetDeltaTFn(beforeDeltaT)
testCases := []struct {
name string
year int
month int
day float64
longitude float64
latitude float64
timeZone float64
zenithShift float64
height float64
expectedRiseCode float64 // -1=拱, -2=沉, -3=明日
expectedSetCode float64
}{
{
name: "极地地区极昼测试",
year: 2023, month: 6, day: 21,
longitude: 0, latitude: 85,
timeZone: 0, zenithShift: 1, height: 0,
expectedRiseCode: -1, // 可能出现拱的情况
expectedSetCode: -1,
},
{
name: "极地地区极夜测试",
year: 2023, month: 12, day: 22,
longitude: 0, latitude: -85,
timeZone: 0, zenithShift: 1, height: 0,
expectedRiseCode: -2, // 可能出现沉的情况
expectedSetCode: -2,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
julianDay := JDECalc(tc.year, tc.month, tc.day)
actualRise := GetMoonRiseTime(julianDay, tc.longitude, tc.latitude,
tc.timeZone, tc.zenithShift, tc.height)
actualSet := GetMoonSetTime(julianDay, tc.longitude, tc.latitude,
tc.timeZone, tc.zenithShift, tc.height)
t.Logf("特殊情况测试结果: 月出=%.6f, 月落=%.6f", actualRise, actualSet)
// 对于极地条件,我们主要验证函数不会崩溃,具体的特殊返回值可能因条件而异
if math.IsNaN(actualRise) || math.IsInf(actualRise, 0) {
t.Errorf("月出时间计算异常: %f", actualRise)
}
if math.IsNaN(actualSet) || math.IsInf(actualSet, 0) {
t.Errorf("月落时间计算异常: %f", actualSet)
}
})
}
}
// floatEquals 比较两个浮点数是否在给定容差内相等
func floatEquals(a, b, tolerance float64) bool {
return math.Abs(a-b) <= tolerance
}
// BenchmarkMoonRiseTime 月出时间计算性能测试
func BenchmarkMoonRiseTime(b *testing.B) {
julianDay := JDECalc(2023, 6, 21)
longitude, latitude := 116.4074, 39.9042
timeZone, zenithShift, height := 8.0, 1.0, 0.0
b.ResetTimer()
for i := 0; i < b.N; i++ {
GetMoonRiseTime(julianDay, longitude, latitude, timeZone, zenithShift, height)
}
}
// BenchmarkMoonSetTime 月落时间计算性能测试
func BenchmarkMoonSetTime(b *testing.B) {
julianDay := JDECalc(2023, 6, 21)
longitude, latitude := 116.4074, 39.9042
timeZone, zenithShift, height := 8.0, 1.0, 0.0
b.ResetTimer()
for i := 0; i < b.N; i++ {
GetMoonSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height)
}
} }

View File

@ -288,48 +288,66 @@ func GetJieqiLoops(year, loop int) []float64 {
return jq return jq
} }
func GetJQTime(Year, Angle int) float64 { //节气时间 func GetJQTime(year, angle int) float64 {
var j int = 1 // Calculate initial day based on angle parity
var Day int var initialDay float64
var tp float64 if angle%2 == 0 {
if Angle%2 == 0 { initialDay = 18
Day = 18
} else { } else {
Day = 3 initialDay = 3
} }
if Angle%10 != 0 {
tp = float64(Angle+15.0) / 30.0 // Calculate temporary factor for month offset
var tempFactor float64
if angle%10 != 0 {
tempFactor = float64(angle+15) / 30.0
} else { } else {
tp = float64(Angle) / 30.0 tempFactor = float64(angle) / 30.0
} }
Month := 3 + tp
if Month > 12 { // Calculate initial month, adjusting if超过 12
Month -= 12 initialMonth := 3.0 + tempFactor
if initialMonth > 12.0 {
initialMonth -= 12.0
} }
JD1 := JDECalc(int(Year), int(Month), float64(Day))
if Angle == 0 { // Calculate initial Julian date
Angle = 360 initialJD := JDECalc(year, int(initialMonth), initialDay)
// Set target angle for iteration; if angle is 0, use 360
targetAngle := float64(angle)
if angle == 0 {
targetAngle = 360.0
} }
for i := 0; i < j; i++ {
for { // Newton-Raphson iteration to find precise Julian date
JD0 := JD1 currentJD := initialJD
stDegree := JQLospec(JD0) - float64(Angle) for {
stDegreep := (JQLospec(JD0+0.000005) - JQLospec(JD0-0.000005)) / 0.00001 previousJD := currentJD
JD1 = JD0 - stDegree/stDegreep errorValue := JQLospec(previousJD, targetAngle) - targetAngle
if math.Abs(JD1-JD0) <= 0.00001 { derivative := (JQLospec(previousJD+0.000005, targetAngle) - JQLospec(previousJD-0.000005, targetAngle)) / 0.00001
break currentJD = previousJD - errorValue/derivative
}
// Check for convergence
if math.Abs(currentJD-previousJD) <= 0.00001 {
break
} }
JD1 -= 0.001
} }
JD1 += 0.001
return TD2UT(JD1, false) // Convert to UT and return
return TD2UT(currentJD, false)
} }
func JQLospec(JD float64) float64 { func JQLospec(JD float64, target float64) float64 {
t := HSunApparentLo(JD) t := HSunApparentLo(JD)
if t <= 12 { if target >= 345 {
t += 360 if t <= 12 {
t += 360
}
} else if target <= 15 {
if t >= 350 {
t -= 360
}
} }
return t return t
} }
@ -391,8 +409,8 @@ func GetWHTime(Year, Angle int) float64 {
} }
for { for {
JD0 := JD1 JD0 := JD1
stDegree := JQLospec(JD0) - float64(Angle) stDegree := JQLospec(JD0, float64(Angle)) - float64(Angle)
stDegreep := (JQLospec(JD0+0.000005) - JQLospec(JD0-0.000005)) / 0.00001 stDegreep := (JQLospec(JD0+0.000005, float64(Angle)) - JQLospec(JD0-0.000005, float64(Angle))) / 0.00001
JD1 = JD0 - stDegree/stDegreep JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 { if math.Abs(JD1-JD0) <= 0.00001 {
break break
@ -503,96 +521,133 @@ func SunTimeAngle(JD, Lon, Lat, TZ float64) float64 {
return timeangle return timeangle
} }
/* // GetSunRiseTime 精确计算日出时间传入当日0时JDE
* 精确计算传入当日0时JDE func GetSunRiseTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 {
*/ return calculateSunRiseSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height, true)
func GetSunRiseTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
var An float64
JD = math.Floor(JD) + 1.5
ntz := math.Round(Lon / 15)
if ZS != 0 {
An = -0.8333
}
An = An - HeightDegreeByLat(HEI, Lat)
tztime := GetSunTZTime(JD, Lon, ntz)
if SunHeight(tztime, Lon, Lat, ntz) < An {
return -2 //极夜
}
if SunHeight(tztime-0.5, Lon, Lat, ntz) > An {
return -1 //极昼
}
//(sin(ho)-sin(φ)*sin(δ2))/(cos(φ)*cos(δ2))
tmp := (Sin(An) - Sin(HSunApparentDec(tztime))*Sin(Lat)) / (Cos(HSunApparentDec(tztime)) * Cos(Lat))
var sunrise float64
if math.Abs(tmp) <= 1 && Lat < 85 {
rzsc := ArcCos(tmp) / 15
sunrise = tztime - rzsc/24 - 25.0/24.0/60.0
} else {
sunrise = tztime
i := 0
//TODO:使用二分法计算
for LowSunHeight(sunrise, Lon, Lat, ntz) > An {
i++
sunrise -= 15.0 / 60.0 / 24.0
if i > 48 {
break
}
}
}
JD1 := sunrise
for {
JD0 := JD1
stDegree := SunHeight(JD0, Lon, Lat, ntz) - An
stDegreep := (SunHeight(JD0+0.000005, Lon, Lat, ntz) - SunHeight(JD0-0.000005, Lon, Lat, ntz)) / 0.00001
JD1 = JD0 - stDegree/stDegreep
if math.Abs(JD1-JD0) <= 0.00001 {
break
}
}
return JD1 - ntz/24 + TZ/24
} }
func GetSunSetTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 {
var An float64 // GetSunSetTime 精确计算日落时间传入当日0时JDE
JD = math.Floor(JD) + 1.5 func GetSunSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 {
ntz := math.Round(Lon / 15) return calculateSunRiseSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height, false)
if ZS != 0 { }
An = -0.8333
// calculateSunRiseSetTime 统一的日出日落计算函数
func calculateSunRiseSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64, isSunrise bool) float64 {
var sunAngle float64
julianDay = math.Floor(julianDay) + 1.5
naturalTimeZone := math.Round(longitude / 15)
// 计算太阳高度角
if zenithShift != 0 {
sunAngle = -0.8333
} }
An = An - HeightDegreeByLat(HEI, Lat) sunAngle = sunAngle - HeightDegreeByLat(height, latitude)
tztime := GetSunTZTime(JD, Lon, ntz)
if SunHeight(tztime, Lon, Lat, ntz) < An { // 获取太阳上中天时间
return -2 //极夜 solarNoonTime := GetSunTZTime(julianDay, longitude, naturalTimeZone)
// 检查极夜极昼条件
polarCondition := checkPolarConditions(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle, isSunrise)
if polarCondition != 0 {
return polarCondition
} }
if SunHeight(tztime+0.5, Lon, Lat, ntz) > An {
return -1 //极昼 // 计算初始估算时间
initialTime := calculateInitialSunTime(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle, isSunrise)
// 牛顿-拉夫逊迭代求精确解
return sunRiseSetNewtonRaphsonIteration(initialTime, longitude, latitude, naturalTimeZone, sunAngle, timeZone)
}
// checkPolarConditions 检查极夜极昼条件
func checkPolarConditions(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle float64, isSunrise bool) float64 {
if SunHeight(solarNoonTime, longitude, latitude, naturalTimeZone) < sunAngle {
return -2 // 极夜
} }
tmp := (Sin(An) - Sin(HSunApparentDec(tztime))*Sin(Lat)) / (Cos(HSunApparentDec(tztime)) * Cos(Lat))
var sundown float64 checkTime := solarNoonTime + 0.5
if math.Abs(tmp) <= 1 && Lat < 85 { if isSunrise {
rzsc := ArcCos(tmp) / 15 checkTime = solarNoonTime - 0.5
sundown = tztime + rzsc/24.0 + 35.0/24.0/60.0 }
} else {
sundown = tztime if SunHeight(checkTime, longitude, latitude, naturalTimeZone) > sunAngle {
i := 0 return -1 // 极昼
for LowSunHeight(sundown, Lon, Lat, ntz) > An { }
i++
sundown += 15.0 / 60.0 / 24.0 return 0 // 正常条件
if i > 48 { }
break
} // calculateInitialSunTime 计算日出日落的初始估算时间
func calculateInitialSunTime(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle float64, isSunrise bool) float64 {
// 使用球面三角法计算: (sin(ho)-sin(φ)*sin(δ))/(cos(φ)*cos(δ))
apparentDeclination := HSunApparentDec(solarNoonTime)
cosHourAngle := (Sin(sunAngle) - Sin(apparentDeclination)*Sin(latitude)) / (Cos(apparentDeclination) * Cos(latitude))
if math.Abs(cosHourAngle) <= 1 && latitude < 85 {
// 使用解析解
hourAngle := ArcCos(cosHourAngle) / 15
timeOffset := 25.0 / 24.0 / 60.0 // 日出偏移
if !isSunrise {
timeOffset = 35.0 / 24.0 / 60.0 // 日落偏移
} }
if isSunrise {
return solarNoonTime - hourAngle/24 - timeOffset
} else {
return solarNoonTime + hourAngle/24 + timeOffset
}
} else {
// 使用迭代逼近法(极地条件)
return iterativeApproach(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle, isSunrise)
} }
JD1 := sundown }
// iterativeApproach 迭代逼近法计算(用于极地等特殊条件)
func iterativeApproach(solarNoonTime, longitude, latitude, naturalTimeZone, sunAngle float64, isSunrise bool) float64 {
estimatedTime := solarNoonTime
stepSize := 15.0 / 60.0 / 24.0 // 15分钟步长
if isSunrise {
stepSize = -stepSize
}
const maxIterations = 48
for i := 0; i < maxIterations && LowSunHeight(estimatedTime, longitude, latitude, naturalTimeZone) > sunAngle; i++ {
estimatedTime += stepSize
}
return estimatedTime
}
// sunRiseSetNewtonRaphsonIteration 牛顿-拉夫逊迭代法求精确解
func sunRiseSetNewtonRaphsonIteration(initialTime, longitude, latitude, naturalTimeZone, sunAngle, timeZone float64) float64 {
const (
convergenceThreshold = 0.00001
derivativeStep = 0.000005
)
currentTime := initialTime
for { for {
JD0 := JD1 previousTime := currentTime
stDegree := SunHeight(JD0, Lon, Lat, ntz) - An
stDegreep := (SunHeight(JD0+0.000005, Lon, Lat, ntz) - SunHeight(JD0-0.000005, Lon, Lat, ntz)) / 0.00001 // 计算函数值f(t) = SunHeight(t) - targetAngle
JD1 = JD0 - stDegree/stDegreep functionValue := SunHeight(previousTime, longitude, latitude, naturalTimeZone) - sunAngle
if math.Abs(JD1-JD0) <= 0.00001 {
// 计算导数f'(t) ≈ (f(t+h) - f(t-h)) / (2h)
derivative := (SunHeight(previousTime+derivativeStep, longitude, latitude, naturalTimeZone) -
SunHeight(previousTime-derivativeStep, longitude, latitude, naturalTimeZone)) / (2 * derivativeStep)
// 牛顿-拉夫逊公式t_new = t_old - f(t) / f'(t)
currentTime = previousTime - functionValue/derivative
// 检查收敛
if math.Abs(currentTime-previousTime) <= convergenceThreshold {
break break
} }
} }
return JD1 - ntz/24 + TZ/24
// 转换为指定时区
return currentTime - naturalTimeZone/24 + timeZone/24
} }
/* /*
@ -643,9 +698,15 @@ func SunAngle(JD, Lon, Lat, TZ float64) float64 {
* 干支 * 干支
*/ */
func GetGZ(year int) string { func GetGZ(year int) string {
tiangan := []string{"庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", ""} tiangan := []string{"庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", ""}
dizhi := []string{"申", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未"} dizhi := []string{"申", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未"}
t := year - (year / 10 * 10) t := year - (year / 10 * 10)
if t < 0 {
t += 10
}
d := year % 12 d := year % 12
return tiangan[t] + dizhi[d] + "年" if d < 0 {
d += 12
}
return tiangan[t] + dizhi[d]
} }

View File

@ -21,5 +21,3 @@ func Date2JDE(date time.Time) float64 {
func JDE2Date(jde float64) time.Time { func JDE2Date(jde float64) time.Time {
return basic.JDE2Date(jde) return basic.JDE2Date(jde)
} }

View File

@ -1,11 +1,19 @@
package calendar package calendar
import ( import (
"fmt"
"math"
"regexp"
"strconv"
"strings"
"time" "time"
"b612.me/astro/basic" "b612.me/astro/basic"
) )
var tiangan = []string{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"}
var dizhi = []string{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"}
const ( const (
JQ_春分 = 15 * iota JQ_春分 = 15 * iota
JQ_清明 JQ_清明
@ -38,7 +46,7 @@ const (
// 返回 农历月,日,是否闰月以及文字描述 // 返回 农历月,日,是否闰月以及文字描述
// 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年 // 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年
// 古代由于定朔定气误差此处计算会与古时不符 // 古代由于定朔定气误差此处计算会与古时不符
func Lunar(year, month, day int, timezone float64) (int, int, bool, string) { func Lunar(year, month, day int, timezone float64) (int, int, int, bool, string) {
return basic.GetLunar(year, month, day, timezone/24.0) return basic.GetLunar(year, month, day, timezone/24.0)
} }
@ -58,31 +66,96 @@ func Solar(year, month, day int, leap bool, timezone float64) time.Time {
// SolarToLunar 公历转农历 // SolarToLunar 公历转农历
// 传入 公历年月日 // 传入 公历年月日
// 返回 农历月,日,是否闰月以及文字描述 // 返回 包含农历信息的Time结构体
// 忽略时区,日期一律按北京时间计算 // 支持年份:[-103,3000]
// 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年 // [-103,1912] 按照古代历法提供的农历信息
// 古代由于定朔定气误差此处计算会与古时不符 // (1912,3000]按现行农历GB/T 33661-2017算法计算
func SolarToLunar(date time.Time) (int, int, bool, string) { func SolarToLunar(date time.Time) (Time, error) {
return basic.GetLunar(date.Year(), int(date.Month()), date.Day(), 8.0/24.0) return innerSolarToLunar(date)
}
func innerSolarToLunar(date time.Time) (Time, error) {
if date.Year() < -103 || date.Year() > 3000 {
return Time{}, fmt.Errorf("日期超出范围")
}
if date.Year() <= 1912 {
return innerSolarToLunarHanQing(date), nil
}
if date.Year() < 2400 {
y, m, d, l, desc := rapidLunarModern(date.Year(), int(date.Month()), date.Day())
if desc == "无法获取农历信息" {
return Time{}, fmt.Errorf("无法获取农历信息")
}
return transformModenLunar2Time(date, y, m, d, l, desc), nil
}
y, m, d, l, desc := basic.GetLunar(date.Year(), int(date.Month()), date.Day(), 8.0/24.0)
return transformModenLunar2Time(date, y, m, d, l, desc), nil
}
func transformModenLunar2Time(date time.Time, year, month, day int, leap bool, desc string) Time {
return Time{
solarTime: date,
lunars: []LunarTime{
{
solarDate: date,
year: year,
month: month,
day: day,
leap: leap,
desc: desc,
comment: "",
ganzhiMonth: commonGanZhiOfMonth(year, month),
eras: nil,
},
},
}
} }
// LunarToSolar 农历转公历 // LunarToSolar 农历转公历
// 传入 农历年份,月,日,是否闰月 // 传入 农历描述,如"二零二零年正月初一","元丰六年十月十二","元嘉二十七年七月庚午日"
// 传出 公历时间 // 传出 包含公里农历信息的Time结构体切片
// 农历年份用公历年份代替,但是岁首需要使用农历岁首 // 传入参数支持如下结构
// 例计算己亥猪年腊月三十日对应的公历即2020年1月24日 // 农历年中文描述+农历月中文描述+农历日中文描述
// 由于农历还未到鼠年故应当传入Solar(2019,12,30,false) // 农历年中文描述+农历月中文描述+干支日中文描述
// 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年 // 年号+农历月中文描述+农历日中文描述
// 古代由于定朔定气误差此处计算会与古时不符 // 年号+农历月中文描述+干支日中文描述
func LunarToSolar(year, month, day int, leap bool) time.Time { // 支持年份:[-103,3000]
jde := basic.GetSolar(year, month, day, leap, 8.0/24.0) func LunarToSolar(desc string) ([]Time, error) {
zone := time.FixedZone("CST", 8*3600) dates, err := innerParseLunar(desc)
return basic.JDE2DateByZone(jde, zone, true) if err != nil {
return nil, err
}
var results []Time
for _, v := range dates {
date, err := SolarToLunar(v)
if err != nil {
return nil, err
}
results = append(results, date)
}
return results, nil
} }
// GanZhi 返回传入年份对应的干支 // LunarToSolarSingle 农历转公历
func GanZhi(year int) string { // 传入 农历年月日,是否闰月
return basic.GetGZ(year) // 传出 包含公里农历信息的Time结构体
// 支持年份:[-103,3000]
// [-103,1912] 按照古代历法提供的农历信息,注意这里农历月份代表的是以当时的历法推定的农历月与正月的距离正月为1二月为2依次类推闰月显示所闰月
// (1912,3000]按现行农历GB/T 33661-2017算法计算
func LunarToSolarSingle(year, month, day int, leap bool) (Time, error) {
if year < -103 || year > 3000 {
return Time{}, fmt.Errorf("年份超出范围")
}
if year <= 1912 {
date := rapidSolarHan2Qing(year, month, day, leap, yearDiffLunar(year, month, day), nil)
return SolarToLunar(date)
}
if year < 2400 {
date := rapidSolarModern(year, month, day, leap)
return SolarToLunar(date)
}
date := Solar(year, month, day, leap, 8.0)
return SolarToLunar(date)
} }
// JieQi 返回传入年份、节气对应的北京时间节气时间 // JieQi 返回传入年份、节气对应的北京时间节气时间
@ -99,43 +172,11 @@ func WuHou(year, term int) time.Time {
return basic.JDE2DateByZone(calcJde, zone, false) return basic.JDE2DateByZone(calcJde, zone, false)
} }
// RapidLunarToSolar 农历转公历(快速查表法) func rapidLunarModern(year, month, day int) (int, int, int, bool, string) {
// 传入 农历年份,月,日,是否闰月
// 传出 公历时间
// 农历年份用公历年份代替,但是岁首需要使用农历岁首
// 例计算己亥猪年腊月三十日对应的公历即2020年1月24日
// 由于农历还未到鼠年故应当传入Solar(2019,12,30,false)
// 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年
// 对于东八区[1900-2400]年的查询,会使用查表法加快计算速度
// 古代由于定朔定气误差此处计算会与古时不符
func RapidLunarToSolar(year, month, day int, leap bool) time.Time {
if year < 1900 || year > 2400 {
jde := basic.GetSolar(year, month, day, leap, 8.0/24.0)
zone := time.FixedZone("CST", 8*3600)
return basic.JDE2DateByZone(jde, zone, true)
}
return rapidSolar(year, month, day, leap)
}
// RapidSolarToLunar 公历转农历(快速查表法)
// 传入 公历年月日
// 返回 农历月,日,是否闰月以及文字描述
// 忽略时区,日期一律按北京时间计算
// 按现行农历GB/T 33661-2017算法计算推荐使用年限为[1929-3000]年
// 古代由于定朔定气误差此处计算会与古时不符
// 对于东八区[1900-2400]年的查询,会使用查表法加快计算速度
func RapidSolarToLunar(date time.Time) (int, int, bool, string) {
if date.Year() < 1900 || date.Year() > 2400 {
return basic.GetLunar(date.Year(), int(date.Month()), date.Day(), 8.0/24.0)
}
return rapidLunar(date.Year(), int(date.Month()), date.Day())
}
func rapidLunar(year, month, day int) (int, int, bool, string) {
var upper = []uint16{32274, 52242, 41001, 30036, 49204, 36918, 25882, 46101, 34854, 22674, 43026, 31145, 51241, 38964, 26997, 47149, 36885, 23717, 44069, 34258, 53266, 41001, 29036, 49178, 37915, 24875, 46090, 34853, 23698, 43026, 31129, 50229, 38970, 26971, 47126, 36874, 24804, 44068, 32242, 52274, 41013, 28086, 48173, 37909, 25898, 46089, 34852, 22706, 43050, 30189, 50203, 38957, 27989, 47123, 35881, 24788, 45076, 32298, 51258, 40986, 29099, 48170, 37906, 25897, 46121, 34836, 21754, 42038, 31190, 50197, 38949, 27986, 48146, 35881, 23860, 44084, 32309, 51245, 39981, 29093, 49189, 37906, 25897, 46121, 35500, 53274, 42011, 30123, 50218, 38949, 27986, 48146, 36889, 23770, 43066, 32282, 52246, 39978, 29028, 49188, 37938, 24885, 45109, 33846, 22678, 42005, 30186, 51209, 39972, 26994, 47146, 35885, 23853, 43051, 32341, 52242, 41001, 29076, 49172, 37930, 25885, 45082, 33835, 22675, 43026, 30121, 50217, 38964, 27002, 46133, 35862, 23770, 44069, 32466, 52242, 41001, 29108, 48180, 36917, 24950, 45101, 33813, 22674, 43026, 31209, 50217, 38954, 26989, 47131, 34859, 23765, 44068, 34322, 52242, 40985, 29082, 48186, 36890, 24874, 45098, 34852, 21746, 42034, 30197, 50229, 37942, 26966, 47125, 35881, 23828, 44052, 32298, 52266, 39981, 28077, 48171, 37909, 24873, 45097, 34836, 22762, 42010, 30172, 50202, 38955, 26963, 47122, 35881, 24852, 43060, 31290, 51253, 39990, 28058, 48149, 37906, 25897, 45097, 33844, 21686, 42037, 30198, 50221, 39957, 29010, 48146, 36905, 24884, 45098, 32365, 52251, 41003, 30101, 49188, 38930, 26905, 47125, 34842, 22747, 43034, 31210, 50218, 39956, 28018, 48170, 35893, 23866, 44086, 34518, 52245, 41001, 30100, 50196, 37930, 25973, 46124, 34861, 22677, 43029, 31209, 51241, 39956, 28010, 48154, 36892, 23853, 44058, 34507, 53266, 41001, 30100, 49204, 37946, 25946, 45110, 34838, 23754, 43018, 31208, 51240, 39988, 27061, 47149, 35893, 24854, 44053, 34442, 53265, 42024, 29098, 49194, 37933, 25965, 45099, 34837, 23753, 44049, 31192, 51220, 39962, 28059, 47126, 35882, 24852, 45074, 31785, 21652, 41012, 29114, 48181, 37910, 25962, 46121, 34834, 22761, 43049, 31220, 50220, 38957, 28053, 48139, 36901, 25874, 46098, 35433, 53273, 42010, 30125, 50202, 38922, 26917, 47140, 36882, 23769, 43065, 31226, 51254, 39958, 29002, 49162, 37924, 24882, 45106, 34421, 53293, 41005, 30165, 50197, 39945, 26980, 47140, 35882, 23797, 43053, 31277, 51243, 40981, 29001, 49161, 37908, 25898, 45082, 34523, 53270, 42026, 30098, 50194, 38953, 27988, 46132, 34874, 23770, 44054, 31210, 51237, 40978, 29097, 48169, 36916, 24950, 45101, 31797, 21605, 42021, 31186, 50194, 38953, 26988, 47130, 34859, 22765, 44042, 32293, 51236, 40978, 29081, 48185, 35898, 24859, 45078, 34826, 21669, 42020, 30130, 50226, 37941, 25974, 46125, 35861, 22762, 44041, 32228, 52260, 39978, 28077, 48157, 36909, 24853, 45075, 33833, 22676, 43028, 31146, 50234, 39962, 26987, 47146, 36882, 24809, 44073, 34260, 52276, 41014, 29082, 49173, 37926, 26898, 46098, 35497, 54313, 43060, 30197, 50221, 38957, 28005, 47141, 36882, 24809, 45097, 32300, 52250, 40987, 29101, 48170, 37925, 26898, 47122, 34841, 22746, 42042, 31195, 50198, 38954, 28004, 48164, 35890, 23861, 44085, 32310, 51245, 40981, 29098, 50185, 37924, 25970, 46122, 34861, 21614, 42029, 31189, 51218, 38953, 27988, 48148, 36906, 23837, 44058, 32299, 52266, 40978, 29097, 49193, 38932, 24954, 45110, 33846, 22682, 42021, 31186, 51218, 39977, 26996, 47156, 35893, 23862, 43053, 32405, 52261, 42002, 29097, 49193, 37932, 25901, 45083, 33835, 22677, 43044, 31122, 51218, 39961, 27994} var upper = []uint16{32274, 52242, 41001, 30036, 49204, 36918, 25882, 46101, 34854, 22674, 43026, 31145, 51241, 38964, 26997, 47149, 36885, 23717, 44069, 34258, 53266, 41001, 29036, 49178, 37915, 24875, 46090, 34853, 23698, 43026, 31129, 50229, 38970, 26971, 47126, 36874, 24804, 44068, 32242, 52274, 41013, 28086, 48173, 37909, 25898, 46089, 34852, 22706, 43050, 30189, 50203, 38957, 27989, 47123, 35881, 24788, 45076, 32298, 51258, 40986, 29099, 48170, 37906, 25897, 46121, 34836, 21754, 42038, 31190, 50197, 38949, 27986, 48146, 35881, 23860, 44084, 32309, 51245, 39981, 29093, 49189, 37906, 25897, 46121, 35500, 53274, 42011, 30123, 50218, 38949, 27986, 48146, 36889, 23770, 43066, 32282, 52246, 39978, 29028, 49188, 37938, 24885, 45109, 33846, 22678, 42005, 30186, 51209, 39972, 26994, 47146, 35885, 23853, 43051, 32341, 52242, 41001, 29076, 49172, 37930, 25885, 45082, 33835, 22675, 43026, 30121, 50217, 38964, 27002, 46133, 35862, 23770, 44069, 32466, 52242, 41001, 29108, 48180, 36917, 24950, 45101, 33813, 22674, 43026, 31209, 50217, 38954, 26989, 47131, 34859, 23765, 44068, 34322, 52242, 40985, 29082, 48186, 36890, 24874, 45098, 34852, 21746, 42034, 30197, 50229, 37942, 26966, 47125, 35881, 23828, 44052, 32298, 52266, 39981, 28077, 48171, 37909, 24873, 45097, 34836, 22762, 42010, 30172, 50202, 38955, 26963, 47122, 35881, 24852, 43060, 31290, 51253, 39990, 28058, 48149, 37906, 25897, 45097, 33844, 21686, 42037, 30198, 50221, 39957, 29010, 48146, 36905, 24884, 45098, 32365, 52251, 41003, 30101, 49188, 38930, 26905, 47125, 34842, 22747, 43034, 31210, 50218, 39956, 28018, 48170, 35893, 23866, 44086, 34518, 52245, 41001, 30100, 50196, 37930, 25973, 46124, 34861, 22677, 43029, 31209, 51241, 39956, 28010, 48154, 36892, 23853, 44058, 34507, 53266, 41001, 30100, 49204, 37946, 25946, 45110, 34838, 23754, 43018, 31208, 51240, 39988, 27061, 47149, 35893, 24854, 44053, 34442, 53265, 42024, 29098, 49194, 37933, 25965, 45099, 34837, 23753, 44049, 31192, 51220, 39962, 28059, 47126, 35882, 24852, 45074, 31785, 21652, 41012, 29114, 48181, 37910, 25962, 46121, 34834, 22761, 43049, 31220, 50220, 38957, 28053, 48139, 36901, 25874, 46098, 35433, 53273, 42010, 30125, 50202, 38922, 26917, 47140, 36882, 23769, 43065, 31226, 51254, 39958, 29002, 49162, 37924, 24882, 45106, 34421, 53293, 41005, 30165, 50197, 39945, 26980, 47140, 35882, 23797, 43053, 31277, 51243, 40981, 29001, 49161, 37908, 25898, 45082, 34523, 53270, 42026, 30098, 50194, 38953, 27988, 46132, 34874, 23770, 44054, 31210, 51237, 40978, 29097, 48169, 36916, 24950, 45101, 31797, 21605, 42021, 31186, 50194, 38953, 26988, 47130, 34859, 22765, 44042, 32293, 51236, 40978, 29081, 48185, 35898, 24859, 45078, 34826, 21669, 42020, 30130, 50226, 37941, 25974, 46125, 35861, 22762, 44041, 32228, 52260, 39978, 28077, 48157, 36909, 24853, 45075, 33833, 22676, 43028, 31146, 50234, 39962, 26987, 47146, 36882, 24809, 44073, 34260, 52276, 41014, 29082, 49173, 37926, 26898, 46098, 35497, 54313, 43060, 30197, 50221, 38957, 28005, 47141, 36882, 24809, 45097, 32300, 52250, 40987, 29101, 48170, 37925, 26898, 47122, 34841, 22746, 42042, 31195, 50198, 38954, 28004, 48164, 35890, 23861, 44085, 32310, 51245, 40981, 29098, 50185, 37924, 25970, 46122, 34861, 21614, 42029, 31189, 51218, 38953, 27988, 48148, 36906, 23837, 44058, 32299, 52266, 40978, 29097, 49193, 38932, 24954, 45110, 33846, 22682, 42021, 31186, 51218, 39977, 26996, 47156, 35893, 23862, 43053, 32405, 52261, 42002, 29097, 49193, 37932, 25901, 45083, 33835, 22677, 43044, 31122, 51218, 39961, 27994}
var lower = []uint8{218, 184, 92, 154, 152, 84, 170, 168, 180, 186, 184, 54, 52, 148, 82, 84, 168, 180, 108, 110, 108, 44, 150, 148, 80, 106, 216, 92, 94, 92, 44, 40, 148, 82, 180, 216, 220, 184, 90, 84, 40, 148, 84, 168, 182, 116, 180, 86, 84, 42, 40, 84, 106, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 152, 76, 84, 170, 168, 180, 186, 180, 52, 154, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 202, 176, 216, 218, 184, 88, 42, 40, 148, 170, 168, 182, 116, 180, 86, 84, 40, 84, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 106, 216, 92, 56, 152, 76, 76, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 182, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148, 148, 200, 216, 184, 184, 92, 88, 42, 40, 148, 170, 168, 180, 186, 180, 86, 84, 40, 84, 84, 104, 116, 108, 172, 78, 76, 166, 168, 84, 106, 216, 92, 156, 88, 76, 72, 168, 212, 180, 184, 58, 52, 84, 74, 72, 164, 104, 116, 182, 108, 44, 150, 148, 74, 72, 88, 108, 220, 92, 46, 44, 148, 74, 168, 212, 180, 184, 92, 88, 40, 148, 84, 170, 168, 180, 186, 180, 52, 42, 168, 84, 170, 104, 116, 108, 172, 46, 44, 164, 84, 212, 106, 216, 92, 92, 88, 44, 164, 164, 212, 218, 184, 186, 180, 84, 42, 72, 164, 180, 108, 182, 108, 172, 86, 84, 40, 84, 84, 108, 110, 92, 174, 172, 84, 42, 168, 212, 218, 184, 92, 172, 168, 84, 84, 168, 212, 180, 184, 86, 52, 150, 164, 84, 170, 104, 116, 182, 108, 46, 44, 164, 82, 212, 216, 108, 220, 92, 44, 40, 148, 164, 212, 218, 184, 184, 90, 84, 42, 40, 164, 180, 108, 116, 182, 172, 84, 42, 40, 84, 84, 108, 110, 92, 172, 86, 84, 42, 168, 212, 218, 184, 92, 154, 152, 84, 170, 168, 180, 116, 184, 54, 52, 148, 74, 80, 168, 180, 108, 174, 108, 44, 150, 148, 80, 106, 216, 108, 220, 92, 44, 40, 148, 82, 180, 216, 92, 184, 90, 84, 40, 148, 148, 168, 182, 116, 182, 172, 84, 42, 40, 84, 170, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 154, 152, 84, 170, 168, 180, 186, 180, 54, 52, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 74, 176, 216, 218, 184, 88, 42, 40, 148, 84, 168, 182, 116, 180, 86, 84, 40, 148, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 212, 216, 92, 92, 152, 76, 72, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 108, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148} var lower = []uint8{218, 184, 92, 154, 152, 84, 170, 168, 180, 186, 184, 54, 52, 148, 82, 84, 168, 180, 108, 110, 108, 44, 150, 148, 80, 106, 216, 92, 94, 92, 44, 40, 148, 82, 180, 216, 220, 184, 90, 84, 40, 148, 84, 168, 182, 116, 180, 86, 84, 42, 40, 84, 106, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 152, 76, 84, 170, 168, 180, 186, 180, 52, 154, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 202, 176, 216, 218, 184, 88, 42, 40, 148, 170, 168, 182, 116, 180, 86, 84, 40, 84, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 106, 216, 92, 56, 152, 76, 76, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 182, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148, 148, 200, 216, 184, 184, 92, 88, 42, 40, 148, 170, 168, 180, 186, 180, 86, 84, 40, 84, 84, 104, 116, 108, 172, 78, 76, 166, 168, 84, 106, 216, 92, 156, 88, 76, 72, 168, 212, 180, 184, 58, 52, 84, 74, 72, 164, 104, 116, 182, 108, 44, 150, 148, 74, 72, 88, 108, 220, 92, 46, 44, 148, 74, 168, 212, 180, 184, 92, 88, 40, 148, 84, 170, 168, 180, 186, 180, 52, 42, 168, 84, 170, 104, 116, 108, 172, 46, 44, 164, 84, 212, 106, 216, 92, 92, 88, 44, 164, 164, 212, 218, 184, 186, 180, 84, 42, 72, 164, 180, 108, 182, 108, 172, 86, 84, 40, 84, 84, 108, 110, 92, 174, 172, 84, 42, 168, 212, 218, 184, 92, 172, 168, 84, 84, 168, 212, 180, 184, 86, 52, 150, 164, 84, 170, 104, 116, 182, 108, 46, 44, 164, 82, 212, 216, 108, 220, 92, 44, 40, 148, 164, 212, 218, 184, 184, 90, 84, 42, 40, 164, 180, 108, 116, 182, 172, 84, 42, 40, 84, 84, 108, 110, 92, 172, 86, 84, 42, 168, 212, 218, 184, 92, 154, 152, 84, 170, 168, 180, 116, 184, 54, 52, 148, 74, 80, 168, 180, 108, 174, 108, 44, 150, 148, 80, 106, 216, 108, 220, 92, 44, 40, 148, 82, 180, 216, 92, 184, 90, 84, 40, 148, 148, 168, 182, 116, 182, 172, 84, 42, 40, 84, 170, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 154, 152, 84, 170, 168, 180, 186, 180, 54, 52, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 74, 176, 216, 218, 184, 88, 42, 40, 148, 84, 168, 182, 116, 180, 86, 84, 40, 148, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 212, 216, 92, 92, 152, 76, 72, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 108, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148}
if year < 1900 || year > 2400 { if year < 1900 || year > 2400 {
return 0, 0, false, "超过日期限制" return 0, 0, 0, false, "超过日期限制"
} }
useGoto := false useGoto := false
recalc: recalc:
@ -144,7 +185,7 @@ recalc:
springMonth := (magic&0x800000)>>23 + 1 springMonth := (magic&0x800000)>>23 + 1
springDay := (magic & 0x7FFFFF) >> 18 springDay := (magic & 0x7FFFFF) >> 18
if !useGoto && springMonth == int32(month) && springDay == int32(day) { if !useGoto && springMonth == int32(month) && springDay == int32(day) {
return 1, 1, false, "正月初一" return year, 1, 1, false, "正月初一"
} }
if !useGoto && (springMonth > int32(month) || (springMonth == int32(month) && springDay > int32(day))) { if !useGoto && (springMonth > int32(month) || (springMonth == int32(month) && springDay > int32(day))) {
year-- year--
@ -187,7 +228,7 @@ recalc:
} else { } else {
result += strday[lday/10] + strmonth[lday%10] result += strday[lday/10] + strmonth[lday%10]
} }
return lunarMonth, lday, isLeap, result return year, lunarMonth, lday, isLeap, result
} }
totalDay += dayofLunar totalDay += dayofLunar
lunarMonth++ lunarMonth++
@ -198,10 +239,10 @@ recalc:
isLeap = false isLeap = false
} }
} }
return 0, 0, false, "无法获取农历信息" return 0, 0, 0, false, "无法获取农历信息"
} }
func rapidSolar(year, month, day int, isLeap bool) time.Time { func rapidSolarModern(year, month, day int, isLeap bool) time.Time {
var upper = []uint16{32274, 52242, 41001, 30036, 49204, 36918, 25882, 46101, 34854, 22674, 43026, 31145, 51241, 38964, 26997, 47149, 36885, 23717, 44069, 34258, 53266, 41001, 29036, 49178, 37915, 24875, 46090, 34853, 23698, 43026, 31129, 50229, 38970, 26971, 47126, 36874, 24804, 44068, 32242, 52274, 41013, 28086, 48173, 37909, 25898, 46089, 34852, 22706, 43050, 30189, 50203, 38957, 27989, 47123, 35881, 24788, 45076, 32298, 51258, 40986, 29099, 48170, 37906, 25897, 46121, 34836, 21754, 42038, 31190, 50197, 38949, 27986, 48146, 35881, 23860, 44084, 32309, 51245, 39981, 29093, 49189, 37906, 25897, 46121, 35500, 53274, 42011, 30123, 50218, 38949, 27986, 48146, 36889, 23770, 43066, 32282, 52246, 39978, 29028, 49188, 37938, 24885, 45109, 33846, 22678, 42005, 30186, 51209, 39972, 26994, 47146, 35885, 23853, 43051, 32341, 52242, 41001, 29076, 49172, 37930, 25885, 45082, 33835, 22675, 43026, 30121, 50217, 38964, 27002, 46133, 35862, 23770, 44069, 32466, 52242, 41001, 29108, 48180, 36917, 24950, 45101, 33813, 22674, 43026, 31209, 50217, 38954, 26989, 47131, 34859, 23765, 44068, 34322, 52242, 40985, 29082, 48186, 36890, 24874, 45098, 34852, 21746, 42034, 30197, 50229, 37942, 26966, 47125, 35881, 23828, 44052, 32298, 52266, 39981, 28077, 48171, 37909, 24873, 45097, 34836, 22762, 42010, 30172, 50202, 38955, 26963, 47122, 35881, 24852, 43060, 31290, 51253, 39990, 28058, 48149, 37906, 25897, 45097, 33844, 21686, 42037, 30198, 50221, 39957, 29010, 48146, 36905, 24884, 45098, 32365, 52251, 41003, 30101, 49188, 38930, 26905, 47125, 34842, 22747, 43034, 31210, 50218, 39956, 28018, 48170, 35893, 23866, 44086, 34518, 52245, 41001, 30100, 50196, 37930, 25973, 46124, 34861, 22677, 43029, 31209, 51241, 39956, 28010, 48154, 36892, 23853, 44058, 34507, 53266, 41001, 30100, 49204, 37946, 25946, 45110, 34838, 23754, 43018, 31208, 51240, 39988, 27061, 47149, 35893, 24854, 44053, 34442, 53265, 42024, 29098, 49194, 37933, 25965, 45099, 34837, 23753, 44049, 31192, 51220, 39962, 28059, 47126, 35882, 24852, 45074, 31785, 21652, 41012, 29114, 48181, 37910, 25962, 46121, 34834, 22761, 43049, 31220, 50220, 38957, 28053, 48139, 36901, 25874, 46098, 35433, 53273, 42010, 30125, 50202, 38922, 26917, 47140, 36882, 23769, 43065, 31226, 51254, 39958, 29002, 49162, 37924, 24882, 45106, 34421, 53293, 41005, 30165, 50197, 39945, 26980, 47140, 35882, 23797, 43053, 31277, 51243, 40981, 29001, 49161, 37908, 25898, 45082, 34523, 53270, 42026, 30098, 50194, 38953, 27988, 46132, 34874, 23770, 44054, 31210, 51237, 40978, 29097, 48169, 36916, 24950, 45101, 31797, 21605, 42021, 31186, 50194, 38953, 26988, 47130, 34859, 22765, 44042, 32293, 51236, 40978, 29081, 48185, 35898, 24859, 45078, 34826, 21669, 42020, 30130, 50226, 37941, 25974, 46125, 35861, 22762, 44041, 32228, 52260, 39978, 28077, 48157, 36909, 24853, 45075, 33833, 22676, 43028, 31146, 50234, 39962, 26987, 47146, 36882, 24809, 44073, 34260, 52276, 41014, 29082, 49173, 37926, 26898, 46098, 35497, 54313, 43060, 30197, 50221, 38957, 28005, 47141, 36882, 24809, 45097, 32300, 52250, 40987, 29101, 48170, 37925, 26898, 47122, 34841, 22746, 42042, 31195, 50198, 38954, 28004, 48164, 35890, 23861, 44085, 32310, 51245, 40981, 29098, 50185, 37924, 25970, 46122, 34861, 21614, 42029, 31189, 51218, 38953, 27988, 48148, 36906, 23837, 44058, 32299, 52266, 40978, 29097, 49193, 38932, 24954, 45110, 33846, 22682, 42021, 31186, 51218, 39977, 26996, 47156, 35893, 23862, 43053, 32405, 52261, 42002, 29097, 49193, 37932, 25901, 45083, 33835, 22677, 43044, 31122, 51218, 39961, 27994} var upper = []uint16{32274, 52242, 41001, 30036, 49204, 36918, 25882, 46101, 34854, 22674, 43026, 31145, 51241, 38964, 26997, 47149, 36885, 23717, 44069, 34258, 53266, 41001, 29036, 49178, 37915, 24875, 46090, 34853, 23698, 43026, 31129, 50229, 38970, 26971, 47126, 36874, 24804, 44068, 32242, 52274, 41013, 28086, 48173, 37909, 25898, 46089, 34852, 22706, 43050, 30189, 50203, 38957, 27989, 47123, 35881, 24788, 45076, 32298, 51258, 40986, 29099, 48170, 37906, 25897, 46121, 34836, 21754, 42038, 31190, 50197, 38949, 27986, 48146, 35881, 23860, 44084, 32309, 51245, 39981, 29093, 49189, 37906, 25897, 46121, 35500, 53274, 42011, 30123, 50218, 38949, 27986, 48146, 36889, 23770, 43066, 32282, 52246, 39978, 29028, 49188, 37938, 24885, 45109, 33846, 22678, 42005, 30186, 51209, 39972, 26994, 47146, 35885, 23853, 43051, 32341, 52242, 41001, 29076, 49172, 37930, 25885, 45082, 33835, 22675, 43026, 30121, 50217, 38964, 27002, 46133, 35862, 23770, 44069, 32466, 52242, 41001, 29108, 48180, 36917, 24950, 45101, 33813, 22674, 43026, 31209, 50217, 38954, 26989, 47131, 34859, 23765, 44068, 34322, 52242, 40985, 29082, 48186, 36890, 24874, 45098, 34852, 21746, 42034, 30197, 50229, 37942, 26966, 47125, 35881, 23828, 44052, 32298, 52266, 39981, 28077, 48171, 37909, 24873, 45097, 34836, 22762, 42010, 30172, 50202, 38955, 26963, 47122, 35881, 24852, 43060, 31290, 51253, 39990, 28058, 48149, 37906, 25897, 45097, 33844, 21686, 42037, 30198, 50221, 39957, 29010, 48146, 36905, 24884, 45098, 32365, 52251, 41003, 30101, 49188, 38930, 26905, 47125, 34842, 22747, 43034, 31210, 50218, 39956, 28018, 48170, 35893, 23866, 44086, 34518, 52245, 41001, 30100, 50196, 37930, 25973, 46124, 34861, 22677, 43029, 31209, 51241, 39956, 28010, 48154, 36892, 23853, 44058, 34507, 53266, 41001, 30100, 49204, 37946, 25946, 45110, 34838, 23754, 43018, 31208, 51240, 39988, 27061, 47149, 35893, 24854, 44053, 34442, 53265, 42024, 29098, 49194, 37933, 25965, 45099, 34837, 23753, 44049, 31192, 51220, 39962, 28059, 47126, 35882, 24852, 45074, 31785, 21652, 41012, 29114, 48181, 37910, 25962, 46121, 34834, 22761, 43049, 31220, 50220, 38957, 28053, 48139, 36901, 25874, 46098, 35433, 53273, 42010, 30125, 50202, 38922, 26917, 47140, 36882, 23769, 43065, 31226, 51254, 39958, 29002, 49162, 37924, 24882, 45106, 34421, 53293, 41005, 30165, 50197, 39945, 26980, 47140, 35882, 23797, 43053, 31277, 51243, 40981, 29001, 49161, 37908, 25898, 45082, 34523, 53270, 42026, 30098, 50194, 38953, 27988, 46132, 34874, 23770, 44054, 31210, 51237, 40978, 29097, 48169, 36916, 24950, 45101, 31797, 21605, 42021, 31186, 50194, 38953, 26988, 47130, 34859, 22765, 44042, 32293, 51236, 40978, 29081, 48185, 35898, 24859, 45078, 34826, 21669, 42020, 30130, 50226, 37941, 25974, 46125, 35861, 22762, 44041, 32228, 52260, 39978, 28077, 48157, 36909, 24853, 45075, 33833, 22676, 43028, 31146, 50234, 39962, 26987, 47146, 36882, 24809, 44073, 34260, 52276, 41014, 29082, 49173, 37926, 26898, 46098, 35497, 54313, 43060, 30197, 50221, 38957, 28005, 47141, 36882, 24809, 45097, 32300, 52250, 40987, 29101, 48170, 37925, 26898, 47122, 34841, 22746, 42042, 31195, 50198, 38954, 28004, 48164, 35890, 23861, 44085, 32310, 51245, 40981, 29098, 50185, 37924, 25970, 46122, 34861, 21614, 42029, 31189, 51218, 38953, 27988, 48148, 36906, 23837, 44058, 32299, 52266, 40978, 29097, 49193, 38932, 24954, 45110, 33846, 22682, 42021, 31186, 51218, 39977, 26996, 47156, 35893, 23862, 43053, 32405, 52261, 42002, 29097, 49193, 37932, 25901, 45083, 33835, 22677, 43044, 31122, 51218, 39961, 27994}
var lower = []uint8{218, 184, 92, 154, 152, 84, 170, 168, 180, 186, 184, 54, 52, 148, 82, 84, 168, 180, 108, 110, 108, 44, 150, 148, 80, 106, 216, 92, 94, 92, 44, 40, 148, 82, 180, 216, 220, 184, 90, 84, 40, 148, 84, 168, 182, 116, 180, 86, 84, 42, 40, 84, 106, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 152, 76, 84, 170, 168, 180, 186, 180, 52, 154, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 202, 176, 216, 218, 184, 88, 42, 40, 148, 170, 168, 182, 116, 180, 86, 84, 40, 84, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 106, 216, 92, 56, 152, 76, 76, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 182, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148, 148, 200, 216, 184, 184, 92, 88, 42, 40, 148, 170, 168, 180, 186, 180, 86, 84, 40, 84, 84, 104, 116, 108, 172, 78, 76, 166, 168, 84, 106, 216, 92, 156, 88, 76, 72, 168, 212, 180, 184, 58, 52, 84, 74, 72, 164, 104, 116, 182, 108, 44, 150, 148, 74, 72, 88, 108, 220, 92, 46, 44, 148, 74, 168, 212, 180, 184, 92, 88, 40, 148, 84, 170, 168, 180, 186, 180, 52, 42, 168, 84, 170, 104, 116, 108, 172, 46, 44, 164, 84, 212, 106, 216, 92, 92, 88, 44, 164, 164, 212, 218, 184, 186, 180, 84, 42, 72, 164, 180, 108, 182, 108, 172, 86, 84, 40, 84, 84, 108, 110, 92, 174, 172, 84, 42, 168, 212, 218, 184, 92, 172, 168, 84, 84, 168, 212, 180, 184, 86, 52, 150, 164, 84, 170, 104, 116, 182, 108, 46, 44, 164, 82, 212, 216, 108, 220, 92, 44, 40, 148, 164, 212, 218, 184, 184, 90, 84, 42, 40, 164, 180, 108, 116, 182, 172, 84, 42, 40, 84, 84, 108, 110, 92, 172, 86, 84, 42, 168, 212, 218, 184, 92, 154, 152, 84, 170, 168, 180, 116, 184, 54, 52, 148, 74, 80, 168, 180, 108, 174, 108, 44, 150, 148, 80, 106, 216, 108, 220, 92, 44, 40, 148, 82, 180, 216, 92, 184, 90, 84, 40, 148, 148, 168, 182, 116, 182, 172, 84, 42, 40, 84, 170, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 154, 152, 84, 170, 168, 180, 186, 180, 54, 52, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 74, 176, 216, 218, 184, 88, 42, 40, 148, 84, 168, 182, 116, 180, 86, 84, 40, 148, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 212, 216, 92, 92, 152, 76, 72, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 108, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148} var lower = []uint8{218, 184, 92, 154, 152, 84, 170, 168, 180, 186, 184, 54, 52, 148, 82, 84, 168, 180, 108, 110, 108, 44, 150, 148, 80, 106, 216, 92, 94, 92, 44, 40, 148, 82, 180, 216, 220, 184, 90, 84, 40, 148, 84, 168, 182, 116, 180, 86, 84, 42, 40, 84, 106, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 152, 76, 84, 170, 168, 180, 186, 180, 52, 154, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 202, 176, 216, 218, 184, 88, 42, 40, 148, 170, 168, 182, 116, 180, 86, 84, 40, 84, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 106, 216, 92, 56, 152, 76, 76, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 182, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148, 148, 200, 216, 184, 184, 92, 88, 42, 40, 148, 170, 168, 180, 186, 180, 86, 84, 40, 84, 84, 104, 116, 108, 172, 78, 76, 166, 168, 84, 106, 216, 92, 156, 88, 76, 72, 168, 212, 180, 184, 58, 52, 84, 74, 72, 164, 104, 116, 182, 108, 44, 150, 148, 74, 72, 88, 108, 220, 92, 46, 44, 148, 74, 168, 212, 180, 184, 92, 88, 40, 148, 84, 170, 168, 180, 186, 180, 52, 42, 168, 84, 170, 104, 116, 108, 172, 46, 44, 164, 84, 212, 106, 216, 92, 92, 88, 44, 164, 164, 212, 218, 184, 186, 180, 84, 42, 72, 164, 180, 108, 182, 108, 172, 86, 84, 40, 84, 84, 108, 110, 92, 174, 172, 84, 42, 168, 212, 218, 184, 92, 172, 168, 84, 84, 168, 212, 180, 184, 86, 52, 150, 164, 84, 170, 104, 116, 182, 108, 46, 44, 164, 82, 212, 216, 108, 220, 92, 44, 40, 148, 164, 212, 218, 184, 184, 90, 84, 42, 40, 164, 180, 108, 116, 182, 172, 84, 42, 40, 84, 84, 108, 110, 92, 172, 86, 84, 42, 168, 212, 218, 184, 92, 154, 152, 84, 170, 168, 180, 116, 184, 54, 52, 148, 74, 80, 168, 180, 108, 174, 108, 44, 150, 148, 80, 106, 216, 108, 220, 92, 44, 40, 148, 82, 180, 216, 92, 184, 90, 84, 40, 148, 148, 168, 182, 116, 182, 172, 84, 42, 40, 84, 170, 104, 108, 174, 172, 84, 84, 168, 84, 212, 216, 92, 92, 154, 152, 84, 170, 168, 180, 186, 180, 54, 52, 148, 74, 80, 168, 180, 108, 108, 46, 44, 150, 148, 80, 104, 216, 92, 94, 92, 44, 148, 148, 74, 176, 216, 218, 184, 88, 42, 40, 148, 84, 168, 182, 116, 180, 86, 84, 40, 148, 84, 106, 232, 108, 174, 172, 76, 42, 168, 84, 212, 216, 92, 92, 152, 76, 72, 168, 212, 180, 186, 180, 52, 150, 148, 72, 168, 104, 180, 108, 108, 46, 44, 148, 74, 72, 104, 108, 220, 94, 92, 44, 148}
if year < 1900 || year > 2400 { if year < 1900 || year > 2400 {
@ -236,3 +277,241 @@ func rapidSolar(year, month, day int, isLeap bool) time.Time {
} }
return time.Time{} return time.Time{}
} }
// 中文数字到阿拉伯数字的映射
var chineseNumbers = map[string]int{
"元": 1, "一": 1, "二": 2, "三": 3, "四": 4, "五": 5,
"六": 6, "七": 7, "八": 8, "九": 9, "十": 10,
"十一": 11, "十二": 12, "十三": 13, "十四": 14, "十五": 15,
"十六": 16, "十七": 17, "十八": 18, "十九": 19, "二十": 20,
"廿一": 21, "廿二": 22, "廿三": 23, "廿四": 24, "廿五": 25,
"廿六": 26, "廿七": 27, "廿八": 28, "廿九": 29, "三十": 30, "卅一": 31,
}
var chineseDays = map[string]int{
"初一": 1, "初二": 2, "初三": 3, "初四": 4, "初五": 5,
"初六": 6, "初七": 7, "初八": 8, "初九": 9, "初十": 10,
"十一": 11, "十二": 12, "十三": 13, "十四": 14, "十五": 15,
"十六": 16, "十七": 17, "十八": 18, "十九": 19, "二十": 20,
"廿一": 21, "廿二": 22, "廿三": 23, "廿四": 24, "廿五": 25,
"廿六": 26, "廿七": 27, "廿八": 28, "廿九": 29, "三十": 30, "卅一": 31,
}
// 中文月份到数字的映射
var chineseMonths = map[string]int{
"正": 1, "腊": 12, "冬": 11, "十一": 11, "十二": 12,
"一": 1, "二": 2, "三": 3, "四": 4, "五": 5, "六": 6,
"七": 7, "八": 8, "九": 9, "十": 10,
}
func parseChineseDate(dateStr string) (LunarTime, error) {
var result LunarTime
var err error
result.desc = dateStr
dateStr = "公元" + dateStr
// 正则表达式匹配日期格式
re := regexp.MustCompile(`^([\p{Han}]+?)([一二三四五六七八九十零〇\d]*?元?)年([\p{Han}\d]+?)月([\p{Han}\d]+?)日?$`)
matches := re.FindStringSubmatch(dateStr)
if len(matches) < 5 {
return result, fmt.Errorf("无效的日期格式: %s", dateStr)
}
matches[1] = strings.TrimPrefix(matches[1], "公元")
// 提取年号
result.comment = matches[1]
// 转换年份
if result.comment != "" {
result.year, err = convertChineseNumber(matches[2])
if err != nil {
return result, fmt.Errorf("无效的年份: %s", matches[2])
}
} else {
// 直接转换年份
if m, _ := regexp.MatchString("\\d+", matches[2]); m {
result.year, err = strconv.Atoi(matches[2])
if err != nil {
return result, fmt.Errorf("无效的年份: %s", matches[2])
}
} else {
result.year = transfer(matches[2], true)
}
}
// 转换月份
monthStr := matches[3]
if strings.HasPrefix(monthStr, "闰") {
result.leap = true
monthStr = strings.TrimPrefix(monthStr, "闰")
}
if month, ok := chineseMonths[monthStr]; ok {
result.month = month
} else {
if m, _ := regexp.MatchString("\\d+", monthStr); m {
result.month, err = strconv.Atoi(monthStr)
} else {
// 尝试将月份字符串转换为数字
result.month, err = convertChineseNumber(monthStr)
}
if err != nil {
return result, fmt.Errorf("无效的月份: %s", monthStr)
}
}
// 转换日期
dayStr := matches[4]
//判断是否是干支日
if len(dayStr) == 6 && strings.ContainsAny(dayStr, "甲乙丙丁戊己庚辛壬癸子丑寅卯辰巳午未申酉戌亥") {
// 临时使用干支月代替
result.ganzhiMonth = dayStr
result.day = 0
return result, nil
}
if day, ok := chineseDays[dayStr]; ok {
result.day = day
} else {
if m, _ := regexp.MatchString("\\d+", dayStr); m {
result.day, err = strconv.Atoi(dayStr)
if err != nil {
return result, fmt.Errorf("无效的日期: %s", dayStr)
}
return result, nil
}
// 尝试将日期字符串转换为数字
result.day, err = convertChineseNumber(dayStr)
if err != nil {
return result, fmt.Errorf("无效的日期: %s", dayStr)
}
}
return result, nil
}
// convertChineseNumber 将中文数字转换为阿拉伯数字
func convertChineseNumber(chineseNum string) (int, error) {
if num, ok := chineseNumbers[chineseNum]; ok {
return num, nil
}
return transfer(chineseNum, false), nil
}
func number2Chinese(num int, isDirectTrans bool) string {
chs := []string{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"}
if isDirectTrans {
var res string
for i := 0; i < 4; i++ {
tmp := num / (int(math.Pow10(3 - i)))
if tmp == 0 && i == 0 {
continue
}
if tmp < 0 {
res = "负"
num = -num
}
res += chs[tmp]
num = num % (int(math.Pow10(3 - i)))
}
return res
}
if num < 0 || num > 99 {
return ""
}
if num < 10 {
return chs[num]
}
if num == 10 {
return "十"
}
if num < 20 {
return "十" + chs[num-10]
}
if num%10 == 0 {
return chs[num/10] + "十"
}
return chs[num/10] + "十" + chs[num%10]
}
func transfer(msg string, direct bool) int {
keyMap := map[rune]int{
'': 0, '零': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10, '百': 100, '千': 1000, '万': 10000, '亿': 100000000, '两': 2, '俩': 2,
}
result := 0
if direct {
for _, num := range []rune(msg) {
if val, match := keyMap[num]; match {
result = result*10 + val
} else {
return 0
}
}
return result
}
secCache := 0
thrCache := 0
fKWord := map[rune]int{'百': 100, '千': 1000, '万': 10000, '亿': 100000000}
for _, num := range []rune(msg) {
if _, match := fKWord[num]; !match {
if num == '十' && thrCache != 0 {
thrCache *= keyMap[num]
} else {
thrCache += keyMap[num]
}
} else {
if fKWord[num] < 10000 {
secCache += thrCache * fKWord[num]
thrCache = 0
} else {
secCache += thrCache
thrCache = 0
if secCache == 0 {
result *= fKWord[num]
continue
}
result += secCache * fKWord[num]
secCache = 0
}
}
}
result += secCache + thrCache
return result
}
// GanZhiOfYear 返回传入年份对应的干支
func GanZhiOfYear(year int) string {
return basic.GetGZ(year)
}
// GanZhiOfDay
func GanZhiOfDay(t time.Time) string {
jde := Date2JDE(time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local))
diff := int(jde - 2451550.5)
if diff >= 0 {
return tiangan[diff%10] + dizhi[diff%12]
}
return tiangan[(diff%10+10)%10] + dizhi[(diff%12+12)%12]
}
// 获取每年建寅月的天干
func tianGanIndexForFirstMonth(year int) int {
diff := (year - 1998) * 2
if diff >= 0 {
return diff % 10
}
return (diff%10 + 10) % 10
}
// commonGanZhiOfMonth 返回常规以建寅为正月时,指定农历月份的干支
func commonGanZhiOfMonth(year, month int) string {
start := tianGanIndexForFirstMonth(year)
index := (start + month - 1) % 10
return tiangan[index] + dizhi[(month+1)%12]
}
func ganZhiOfDayIndex(t time.Time) (int, int) {
jde := Date2JDE(time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local))
diff := int(jde - 2451550.5)
if diff >= 0 {
return diff % 10, diff % 12
}
return (diff%10 + 10) % 10, (diff%12 + 12) % 10
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,407 @@
package calendar
func liaoJinYuanCals() map[int]uint32 {
return map[int]uint32{
949: 2996838400,
955: 1237097216,
958: 2858129152,
959: 1787832832,
961: 766088192,
964: 2574266112,
965: 1232086016,
973: 2464163072,
985: 3031177216,
986: 1788881664,
994: 3645910016,
999: 2775716864,
1001: 3530398464,
1012: 3579124224,
1015: 2513671936,
1020: 2992512000,
1021: 1787833856,
1024: 727723008,
1025: 2507153408,
1029: 1783730688,
1039: 3667270400,
1040: 3046125056,
1044: 2463113472,
1045: 3378156800,
1049: 2907710464,
1053: 2461767424,
1056: 1823052800,
1059: 2605723136,
1064: 3912439040,
1070: 1255156992,
1073: 2991597824,
1075: 3601470208,
1077: 2513836800,
1078: 2511351296,
1080: 2763790592,
1094: 728372224,
1105: 2733216256,
1113: 635048960,
1121: 1269470464,
1129: 2874414592,
1134: 3529513728,
1145: 3041761536,
1147: 3445629184,
1152: 1689265920,
1155: 1530929920,
1163: 3595576320,
1168: 2461018624,
1176: 628108288,
1178: 2839221504,
1184: 1264594176,
1198: 3040880384,
1207: 2904563200,
1209: 727721472,
1239: 1370498304,
1250: 3576701440,
1251: 1520769024,
1253: 1523588864,
1256: 2732596480,
1258: 3511690240,
1263: 2513447168,
1270: 3047528192,
1273: 1169888512,
1276: 1784254976,
}
}
func liaoJinYuanEras() []Era {
return []Era{
{
Year: 1264,
Emperor: "元世祖",
OtherNianHaoStart: "至元",
Dynasty: "元",
},
{
Year: 1260,
Emperor: "元世祖",
Nianhao: "中统",
Dynasty: "元",
},
{
Year: 1251,
Emperor: "元宪宗",
Nianhao: "元宪宗",
Dynasty: "元",
},
{
Year: 1249,
Emperor: "元定宗后",
Nianhao: "元定宗后",
Dynasty: "元",
},
{
Year: 1246,
Emperor: "元定宗",
Nianhao: "元定宗",
Dynasty: "元",
},
{
Year: 1242,
Emperor: "元太宗",
Nianhao: "元太宗后",
Dynasty: "元",
},
{
Year: 1234,
Emperor: "元太宗",
OtherNianHaoStart: "元太宗",
Dynasty: "元",
Offset: 5,
},
{
Year: 1232,
Emperor: "金哀宗",
Nianhao: "天兴",
Dynasty: "金",
},
{
Year: 1224,
Emperor: "金哀宗",
Nianhao: "正大",
Dynasty: "金",
},
{
Year: 1222,
Emperor: "金宣宗",
OtherNianHaoStart: "元光",
Dynasty: "金",
},
{
Year: 1217,
Emperor: "金宣宗",
OtherNianHaoStart: "兴定",
Dynasty: "金",
},
{
Year: 1213,
Emperor: "金宣宗",
OtherNianHaoStart: "贞佑",
Dynasty: "金",
},
{
Year: 1213,
Emperor: "金宣宗",
OtherNianHaoStart: "至宁",
Dynasty: "金",
},
{
Year: 1212,
Emperor: "金卫绍王",
OtherNianHaoStart: "崇庆",
Dynasty: "金",
},
{
Year: 1209,
Emperor: "金卫绍王",
Nianhao: "大安",
Dynasty: "金",
},
{
Year: 1201,
Emperor: "金章宗",
Nianhao: "泰和",
Dynasty: "金",
},
{
Year: 1196,
Emperor: "金章宗",
OtherNianHaoStart: "承安",
Dynasty: "金",
},
{
Year: 1190,
Emperor: "金章宗",
Nianhao: "明昌",
Dynasty: "金",
},
{
Year: 1161,
Emperor: "金世宗",
OtherNianHaoStart: "大定",
Dynasty: "金",
},
{
Year: 1156,
Emperor: "金海陵王",
OtherNianHaoStart: "正隆",
Dynasty: "金",
},
{
Year: 1153,
Emperor: "金海陵王",
OtherNianHaoStart: "贞元",
Dynasty: "金",
},
{
Year: 1149,
Emperor: "金海陵王",
OtherNianHaoStart: "天德",
Dynasty: "金",
},
{
Year: 1141,
Emperor: "金熙宗",
Nianhao: "皇统",
Dynasty: "金",
},
{
Year: 1138,
Emperor: "金熙宗",
Nianhao: "天眷",
Dynasty: "金",
},
{
Year: 1125,
Emperor: "金太宗",
OtherNianHaoStart: "天会",
Dynasty: "金",
Offset: 2,
},
{
Year: 1121,
Emperor: "辽天祚帝",
Nianhao: "保大",
Dynasty: "辽",
},
{
Year: 1111,
Emperor: "辽天祚帝",
Nianhao: "天庆",
Dynasty: "辽",
},
{
Year: 1101,
Emperor: "辽天祚帝",
OtherNianHaoStart: "乾统",
Dynasty: "辽",
},
{
Year: 1095,
Emperor: "辽道宗",
Nianhao: "寿昌",
Dynasty: "辽",
},
{
Year: 1085,
Emperor: "辽道宗",
Nianhao: "大安",
Dynasty: "辽",
},
{
Year: 1075,
Emperor: "辽道宗",
Nianhao: "大康",
Dynasty: "辽",
},
{
Year: 1065,
Emperor: "辽道宗",
Nianhao: "咸雍",
Dynasty: "辽",
},
{
Year: 1055,
Emperor: "辽道宗",
OtherNianHaoStart: "清宁",
Dynasty: "辽",
},
{
Year: 1032,
Emperor: "辽兴宗",
OtherNianHaoStart: "重熙",
Dynasty: "辽",
},
{
Year: 1031,
Emperor: "辽兴宗",
OtherNianHaoStart: "景福",
Dynasty: "辽",
},
{
Year: 1021,
Emperor: "辽圣宗",
OtherNianHaoStart: "太平",
Dynasty: "辽",
},
{
Year: 1012,
Emperor: "辽圣宗",
OtherNianHaoStart: "开泰",
Dynasty: "辽",
},
{
Year: 983,
Emperor: "辽圣宗",
OtherNianHaoStart: "统和",
Dynasty: "辽",
},
{
Year: 979,
Emperor: "辽景宗",
OtherNianHaoStart: "乾亨",
Dynasty: "辽",
},
{
Year: 969,
Emperor: "辽景宗",
OtherNianHaoStart: "保宁",
Dynasty: "辽",
},
{
Year: 951,
Emperor: "辽穆宗",
OtherNianHaoStart: "应历",
Dynasty: "辽",
},
{
Year: 947,
Emperor: "辽世宗",
OtherNianHaoStart: "天禄",
Dynasty: "辽",
},
{
Year: 947,
Emperor: "辽太宗",
Nianhao: "大同",
Dynasty: "辽",
},
{
Year: 939,
Emperor: "辽太宗",
OtherNianHaoStart: "会同",
Dynasty: "辽",
},
}
}
func liaoJinYuanEraMap() map[string][][]int {
return map[string][][]int{
"中统": [][]int{{1260, 1264}},
"元宪宗": [][]int{{1251, 1259}},
"元定宗后": [][]int{{1249, 1250}},
"元定宗": [][]int{{1246, 1248}},
"元太宗后": [][]int{{1242, 1245}},
"元太宗": [][]int{{1229, 1241}},
"天兴": [][]int{{1232, 1229}},
"正大": [][]int{{1224, 1231}},
"元光": [][]int{{1222, 1223}},
"兴定": [][]int{{1217, 1222}},
"贞佑": [][]int{{1213, 1217}},
"至宁": [][]int{{1213, 1213}},
"崇庆": [][]int{{1212, 1213}},
"泰和": [][]int{{1201, 1208}},
"承安": [][]int{{1196, 1200}},
"明昌": [][]int{{1190, 1196}},
"大定": [][]int{{1161, 1189}},
"正隆": [][]int{{1156, 1161}},
"贞元": [][]int{{1153, 1156}},
"天德": [][]int{{1149, 1153}},
"皇统": [][]int{{1141, 1149}},
"天眷": [][]int{{1138, 1140}},
"天会": [][]int{{1123, 1137}},
"保大": [][]int{{1121, 1125}},
"天庆": [][]int{{1111, 1120}},
"乾统": [][]int{{1101, 1110}},
"寿昌": [][]int{{1095, 1101}},
"大安": [][]int{{1085, 1094}, {1209, 1212}},
"大康": [][]int{{1075, 1084}},
"咸雍": [][]int{{1065, 1074}},
"清宁": [][]int{{1055, 1064}},
"重熙": [][]int{{1032, 1055}},
"景福": [][]int{{1031, 1032}},
"太平": [][]int{{1021, 1031}},
"开泰": [][]int{{1012, 1021}},
"统和": [][]int{{983, 1012}},
"乾亨": [][]int{{979, 983}},
"保宁": [][]int{{969, 979}},
"应历": [][]int{{951, 969}},
"天禄": [][]int{{947, 951}},
"大同": [][]int{{947, 947}},
"会同": [][]int{{939, 946}},
}
}
func innerSolarToLunarLiaoJinYuan(date Time) Time {
year := date.solarTime.Year()
month := int(date.solarTime.Month())
day := date.solarTime.Day()
if year >= 947 && year <= 1279 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, liaoJinYuanCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
comment: "",
ganzhiMonth: ganzhiMonth,
eras: innerEras(lyear, liaoJinYuanEras),
})
}
return date
}

View File

@ -0,0 +1,916 @@
package calendar
// 后秦
func houQinCals() map[int]uint32 {
return map[int]uint32{
384: 2862622464,
385: 3042089728,
386: 2874158592,
387: 1431315456,
388: 2863175936,
389: 1788881664,
390: 2874482688,
391: 2863674112,
392: 1431316736,
393: 1789631744,
394: 1453338624,
395: 2863670528,
396: 1431411456,
397: 3578801152,
398: 1454219776,
399: 1432368384,
400: 2862623232,
401: 3579059712,
402: 2907713792,
403: 1432364800,
404: 2863307776,
405: 2862624256,
406: 2907710208,
407: 1432951040,
408: 1431317504,
409: 2863472640,
410: 1520448256,
411: 2865768448,
412: 1432034816,
413: 1431318528,
414: 1520444672,
415: 2865863168,
416: 2863672576,
417: 1431708160,
}
}
func houQinEras() []Era {
return []Era{
{
Year: 416,
Emperor: "后秦末主",
OtherNianHaoStart: "永和",
Dynasty: "后秦",
},
{
Year: 399,
Emperor: "后秦文桓帝",
OtherNianHaoStart: "弘始",
Dynasty: "后秦",
},
{
Year: 394,
Emperor: "后秦文桓帝",
OtherNianHaoStart: "皇初",
Dynasty: "后秦",
},
{
Year: 386,
Emperor: "后秦武昭帝",
OtherNianHaoStart: "建初",
Dynasty: "后秦",
},
{
Year: 384,
Emperor: "后秦武昭帝",
Nianhao: "白雀",
Dynasty: "后秦",
},
}
}
func houQinEraMap() map[string][][]int {
return map[string][][]int{
"永和": [][]int{{416, 417}},
"弘始": [][]int{{399, 416}},
"皇初": [][]int{{394, 399}},
"建初": [][]int{{386, 394}},
"白雀": [][]int{{384, 386}},
}
}
// 北魏、西魏、北周、隋
func weiZhouSuiCals() map[int]uint32 {
return map[int]uint32{
398: 1454219776,
399: 1436562688,
400: 2862623232,
401: 3579059712,
402: 2907713792,
403: 1436559104,
404: 2863307776,
405: 2862624256,
406: 2907710208,
407: 1437145344,
408: 1431317504,
409: 2863472640,
410: 1520448256,
411: 2874157056,
412: 1432034816,
413: 1431318528,
414: 1520444672,
415: 2874251776,
416: 2863672576,
417: 1431708160,
418: 3041932288,
419: 1453337088,
420: 2863931136,
421: 2862625024,
422: 3041928704,
423: 1453988864,
424: 1432366848,
425: 2862621440,
426: 3041957888,
427: 2907712256,
428: 1433215232,
429: 1431319296,
430: 2862622720,
431: 2907905280,
432: 2865770496,
433: 1431315712,
434: 1789499904,
435: 1520446720,
436: 2866160128,
437: 2862625792,
438: 3578800384,
439: 1521262336,
440: 1436561920,
441: 2862622208,
442: 3578960640,
443: 3041930752,
444: 1436558336,
445: 2863175680,
446: 2862623488,
447: 3042254848,
448: 2874159872,
449: 1431316480,
450: 2863373568,
451: 1788882944,
452: 2874156288,
453: 1432033792,
454: 1431317760,
455: 1520443904,
456: 2874218240,
457: 2863671552,
458: 1431641856,
459: 3041931520,
460: 1453336320,
461: 2863897344,
462: 2862624256,
463: 3041927936,
464: 1453988096,
465: 1432365824,
466: 2862620672,
467: 3041957120,
468: 2907711488,
469: 1433181440,
470: 1431318528,
471: 1788880128,
472: 2907904512,
473: 2865769472,
474: 1431314944,
475: 1789499136,
476: 1520445952,
477: 2866126336,
478: 2862625024,
479: 3578799616,
480: 1521196032,
481: 1436560896,
482: 2862621440,
483: 3578927104,
484: 3041929984,
485: 1436557312,
486: 2863174912,
487: 2862622720,
488: 3042221312,
489: 2874158848,
490: 1431315712,
491: 2863307264,
492: 1788882176,
493: 2874155264,
494: 1431901952,
495: 1431316992,
496: 1789763328,
497: 1453338880,
498: 2863670784,
499: 1431575552,
500: 3578801664,
501: 1453335296,
502: 2863798272,
503: 2862623488,
504: 3579191296,
505: 2907714048,
506: 1432365056,
507: 2863439104,
508: 2862624768,
509: 2907710464,
510: 1433082368,
511: 1431317760,
512: 2862621184,
513: 2907772416,
514: 2865768704,
515: 1431641856,
516: 3578802432,
517: 1520444928,
518: 2865994496,
519: 2862624256,
520: 3578798848,
521: 1521129472,
522: 1436560128,
523: 2863669248,
524: 1431377408,
525: 3041928960,
526: 1437441280,
527: 1432367104,
528: 2862621952,
529: 3042154752,
530: 2874158080,
531: 1432363520,
532: 2863240960,
533: 1788881152,
534: 2874547712,
535: 2865770752,
536: 1431316224,
537: 1789696768,
538: 1453338112,
539: 2865767168,
540: 1431476480,
541: 3578800640,
542: 1453334528,
543: 2865796352,
544: 2862622720,
545: 3579124736,
546: 2907713280,
547: 1436558592,
548: 2863372800,
549: 2862623744,
550: 2907709696,
551: 1437210368,
552: 1431316992,
553: 2863537664,
554: 1520447744,
555: 2874156544,
556: 1432099840,
557: 1431318016,
558: 1520444160,
559: 2874316800,
560: 2863672064,
561: 1431314432,
562: 1520997632,
563: 1453336576,
564: 2863963392,
565: 2863673088,
566: 1431315712,
567: 2863405568,
568: 1788882176,
569: 2874155264,
570: 1431967488,
571: 1431316992,
572: 1788878592,
573: 2874184448,
574: 2865767936,
575: 1431641088,
576: 3578801664,
577: 1453335296,
578: 2865960960,
579: 2865769216,
580: 1431314688,
581: 2863240448,
582: 1520445440,
583: 2866158848,
584: 1788882944,
585: 2907710464,
586: 1433147904,
587: 1431317760,
588: 1788879360,
589: 2907837952,
}
}
func weiZhouSuiEras() []Era {
return []Era{
{
Year: 601,
Emperor: "隋文帝",
Nianhao: "仁寿",
Dynasty: "隋",
},
{
Year: 581,
Emperor: "隋文帝",
Nianhao: "开皇",
Dynasty: "隋",
},
{
Year: 579,
Emperor: "北周静帝",
Nianhao: "大象",
Dynasty: "北周",
},
{
Year: 578,
Emperor: "北周宣帝",
OtherNianHaoStart: "宣政",
Dynasty: "北周",
},
{
Year: 572,
Emperor: "北周武帝",
OtherNianHaoStart: "建德",
Dynasty: "北周",
},
{
Year: 566,
Emperor: "北周武帝",
Nianhao: "天和",
Dynasty: "北周",
},
{
Year: 561,
Emperor: "北周武帝",
Nianhao: "保定",
Dynasty: "北周",
},
{
Year: 559,
Emperor: "北周明帝",
Nianhao: "武成",
Dynasty: "北周",
},
{
Year: 557,
Emperor: "北周明帝",
Nianhao: "北周明帝",
Dynasty: "北周",
},
{
Year: 554,
Emperor: "西魏恭帝",
Nianhao: "西魏恭帝",
Dynasty: "西魏",
},
{
Year: 552,
Emperor: "西魏元钦",
Nianhao: "西魏元钦",
Dynasty: "西魏",
},
{
Year: 535,
Emperor: "西魏文帝",
Nianhao: "大统",
Dynasty: "西魏",
},
{
Year: 532,
Emperor: "北魏孝武帝",
Nianhao: "永熙",
Dynasty: "北魏",
},
{
Year: 531,
Emperor: "北魏节闵帝",
OtherNianHaoStart: "中兴",
Dynasty: "北魏",
},
{
Year: 530,
Emperor: "北魏节闵帝",
OtherNianHaoStart: "建明",
Dynasty: "北魏",
},
{
Year: 528,
Emperor: "北魏孝庄帝",
OtherNianHaoStart: "武泰",
Dynasty: "北魏",
},
{
Year: 528,
Emperor: "北魏孝庄帝",
OtherNianHaoStart: "建义",
Dynasty: "北魏",
},
{
Year: 528,
Emperor: "北魏孝庄帝",
Nianhao: "永安",
Dynasty: "北魏",
},
{
Year: 525,
Emperor: "北魏孝明帝",
OtherNianHaoStart: "孝昌",
Dynasty: "北魏",
},
{
Year: 520,
Emperor: "北魏孝明帝",
OtherNianHaoStart: "正光",
Dynasty: "北魏",
},
{
Year: 518,
Emperor: "北魏孝明帝",
OtherNianHaoStart: "神龟",
Dynasty: "北魏",
},
{
Year: 516,
Emperor: "北魏孝明帝",
Nianhao: "熙平",
Dynasty: "北魏",
},
{
Year: 512,
Emperor: "北魏宣武帝",
OtherNianHaoStart: "延昌",
Dynasty: "北魏",
},
{
Year: 508,
Emperor: "北魏宣武帝",
OtherNianHaoStart: "永平",
Dynasty: "北魏",
},
{
Year: 504,
Emperor: "北魏宣武帝",
Nianhao: "正始",
Dynasty: "北魏",
},
{
Year: 500,
Emperor: "北魏宣武帝",
Nianhao: "景明",
Dynasty: "北魏",
},
{
Year: 477,
Emperor: "北魏孝文帝",
Nianhao: "太和",
Dynasty: "北魏",
},
{
Year: 476,
Emperor: "北魏孝文帝",
OtherNianHaoStart: "承明",
Dynasty: "北魏",
},
{
Year: 471,
Emperor: "北魏孝文帝",
OtherNianHaoStart: "延兴",
Dynasty: "北魏",
},
{
Year: 467,
Emperor: "北魏献文帝",
OtherNianHaoStart: "皇兴",
Dynasty: "北魏",
},
{
Year: 466,
Emperor: "北魏献文帝",
OtherNianHaoStart: "天安",
Dynasty: "北魏",
},
{
Year: 460,
Emperor: "北魏文成帝",
Nianhao: "和平",
Dynasty: "北魏",
},
{
Year: 455,
Emperor: "北魏文成帝",
OtherNianHaoStart: "太安",
Dynasty: "北魏",
},
{
Year: 454,
Emperor: "北魏文成帝",
OtherNianHaoStart: "兴光",
Dynasty: "北魏",
},
{
Year: 452,
Emperor: "北魏文成帝",
OtherNianHaoStart: "兴安",
Dynasty: "北魏",
},
{
Year: 451,
Emperor: "北魏太武帝",
OtherNianHaoStart: "正平",
Dynasty: "北魏",
},
{
Year: 440,
Emperor: "北魏太武帝",
OtherNianHaoStart: "太平真君",
Dynasty: "北魏",
},
{
Year: 435,
Emperor: "北魏太武帝",
Nianhao: "太延",
Dynasty: "北魏",
},
{
Year: 432,
Emperor: "北魏太武帝",
Nianhao: "延和",
Dynasty: "北魏",
},
{
Year: 428,
Emperor: "北魏太武帝",
OtherNianHaoStart: "神䴥",
Dynasty: "北魏",
},
{
Year: 424,
Emperor: "北魏太武帝",
Nianhao: "始光",
Dynasty: "北魏",
},
{
Year: 416,
Emperor: "北魏明元帝",
OtherNianHaoStart: "泰常",
Dynasty: "北魏",
},
{
Year: 414,
Emperor: "北魏明元帝",
Nianhao: "神瑞",
Dynasty: "北魏",
},
{
Year: 409,
Emperor: "北魏明元帝",
OtherNianHaoStart: "永兴",
Dynasty: "北魏",
},
{
Year: 404,
Emperor: "北魏道武帝",
OtherNianHaoStart: "天赐",
Dynasty: "北魏",
},
{
Year: 398,
Emperor: "北魏道武帝",
Nianhao: "天兴",
Dynasty: "北魏",
},
{
Year: 396,
Emperor: "北魏道武帝",
OtherNianHaoStart: "皇始",
Dynasty: "北魏",
},
{
Year: 386,
Emperor: "北魏道武帝",
Nianhao: "登国",
Dynasty: "北魏",
},
}
}
func weiZhouSuiEraMap() map[string][][]int {
return map[string][][]int{
//"开皇": [][]int{{581, 600}},
"大象": [][]int{{579, 580}},
"宣政": [][]int{{578, 578}},
"建德": [][]int{{572, 578}},
"天和": [][]int{{566, 572}},
"保定": [][]int{{561, 565}},
"武成": [][]int{{559, 560}},
"北周明帝": [][]int{{557, 558}},
"西魏恭帝": [][]int{{554, 556}},
"西魏元钦": [][]int{{552, 553}},
"大统": [][]int{{535, 551}},
"永熙": [][]int{{532, 534}},
"中兴": [][]int{{531, 531}},
"建明": [][]int{{530, 531}},
"永安": [][]int{{528, 530}},
"建义": [][]int{{528, 528}},
"武泰": [][]int{{528, 528}},
"孝昌": [][]int{{525, 527}},
"正光": [][]int{{520, 525}},
"神龟": [][]int{{518, 520}},
"熙平": [][]int{{516, 518}},
"延昌": [][]int{{512, 515}},
"永平": [][]int{{508, 512}},
"正始": [][]int{{504, 508}},
"景明": [][]int{{500, 503}},
"太和": [][]int{{477, 499}},
"承明": [][]int{{476, 476}},
"延兴": [][]int{{471, 476}},
"皇兴": [][]int{{467, 471}},
"天安": [][]int{{466, 467}},
"和平": [][]int{{460, 466}},
"太安": [][]int{{455, 459}},
"兴光": [][]int{{454, 455}},
"兴安": [][]int{{452, 454}},
"正平": [][]int{{451, 452}},
"太平真君": [][]int{{440, 451}},
"太延": [][]int{{435, 440}},
"延和": [][]int{{432, 434}},
"神䴥": [][]int{{428, 431}},
"始光": [][]int{{424, 428}},
"泰常": [][]int{{416, 423}},
"神瑞": [][]int{{414, 416}},
"永兴": [][]int{{409, 413}},
"天赐": [][]int{{404, 409}},
"天兴": [][]int{{398, 404}},
"皇始": [][]int{{396, 397}},
"登国": [][]int{{386, 396}},
}
}
func beiLiangCals() map[int]uint32 {
return map[int]uint32{
// currect here
412: 1432100352,
413: 1431318528,
414: 1520444672,
415: 2865928704,
416: 2863672576,
417: 1431314944,
418: 1521030912,
419: 1436559872,
420: 2864029440,
421: 2862625024,
422: 3041928704,
423: 1437309952,
424: 1432366848,
425: 2862621440,
426: 3042056192,
427: 2874157824,
428: 1432363264,
429: 2863174912,
430: 2862622720,
431: 2874449152,
432: 2865770496,
433: 1431315712,
434: 1789565440,
435: 1453337856,
436: 2865766912,
437: 1431377664,
438: 3578800384,
439: 1454219008,
}
}
func beiLiangEras() []Era {
return []Era{
{
Year: 433,
Emperor: "北凉哀王",
OtherNianHaoStart: "承和",
Dynasty: "北凉",
},
{
Year: 431,
Emperor: "北凉哀王",
OtherNianHaoStart: "义和",
Dynasty: "北凉",
},
{
Year: 428,
Emperor: "北凉哀王",
OtherNianHaoStart: "承玄",
Dynasty: "北凉",
},
{
Year: 412,
Emperor: "北凉武宣王",
OtherNianHaoStart: "玄始",
Dynasty: "北凉",
},
{
Year: 401,
Emperor: "北凉武宣王",
OtherNianHaoStart: "永安",
Dynasty: "北凉",
},
{
Year: 399,
Emperor: "北凉武宣王",
OtherNianHaoStart: "天玺",
Dynasty: "北凉",
},
{
Year: 397,
Emperor: "北凉武宣王",
Nianhao: "神玺",
Dynasty: "北凉",
},
}
}
func beiLiangEraMap() map[string][][]int {
return map[string][][]int{
"承和": [][]int{{433, 439}},
"义和": [][]int{{431, 433}},
"承玄": [][]int{{428, 431}},
"玄始": [][]int{{412, 428}},
"永安": [][]int{{401, 412}},
"天玺": [][]int{{399, 401}},
"神玺": [][]int{{397, 399}},
}
}
func dongWeiBeiQiCals() map[int]uint32 {
return map[int]uint32{
534: 2874547712,
535: 2865770752,
536: 1431316224,
537: 1789696768,
538: 1453338112,
539: 2865767168,
540: 1431476480,
541: 3578800640,
542: 1453334528,
543: 2865796352,
544: 2862622720,
545: 3579124736,
546: 2907713280,
547: 1436558592,
548: 2863372800,
549: 2862623744,
550: 2907709696,
551: 1432950528,
552: 1431316992,
553: 2863504896,
554: 1520447744,
555: 2865767936,
556: 1432099840,
557: 1431318016,
558: 1520444160,
559: 2865895424,
560: 2863672064,
561: 1431707648,
562: 3041931776,
563: 1436559360,
564: 2863963392,
565: 2862624512,
566: 3041928192,
567: 1437276672,
568: 1432366336,
569: 2862620928,
570: 3041990144,
571: 2874157312,
572: 1433247488,
573: 1431318784,
574: 1788880384,
575: 2874415872,
576: 2865769984,
577: 1431315200,
}
}
func dongWeiBeiQiEras() []Era {
return []Era{
{
Year: 577,
Emperor: "北齐后主",
Nianhao: "承光",
Dynasty: "北齐",
},
{
Year: 570,
Emperor: "北齐后主",
Nianhao: "武平",
Dynasty: "北齐",
},
{
Year: 565,
Emperor: "北齐后主",
OtherNianHaoStart: "天统",
Dynasty: "北齐",
},
{
Year: 562,
Emperor: "北齐武成帝",
OtherNianHaoStart: "河清",
Dynasty: "北齐",
},
{
Year: 561,
Emperor: "北齐武成帝",
OtherNianHaoStart: "太宁",
Dynasty: "北齐",
},
{
Year: 560,
Emperor: "北齐孝昭帝",
OtherNianHaoStart: "皇建",
Dynasty: "北齐",
},
{
Year: 550,
Emperor: "北齐文宣帝",
Nianhao: "天保",
Dynasty: "北齐",
},
{
Year: 543,
Emperor: "东魏孝静帝",
Nianhao: "武定",
Dynasty: "东魏",
},
{
Year: 539,
Emperor: "东魏孝静帝",
OtherNianHaoStart: "兴和",
Dynasty: "东魏",
},
{
Year: 538,
Emperor: "东魏孝静帝",
OtherNianHaoStart: "元象",
Dynasty: "东魏",
},
{
Year: 534,
Emperor: "东魏孝静帝",
Nianhao: "天平",
Dynasty: "东魏",
},
}
}
func dongWeiBeiQiEraMap() map[string][][]int {
return map[string][][]int{
"承光": [][]int{{577, 577}},
"武平": [][]int{{570, 576}},
"天统": [][]int{{565, 569}},
"河清": [][]int{{562, 565}},
"太宁": [][]int{{561, 562}},
"皇建": [][]int{{560, 561}},
"天保": [][]int{{550, 560}},
"武定": [][]int{{543, 549}},
"兴和": [][]int{{539, 542}},
"元象": [][]int{{538, 539}},
"天平": [][]int{{534, 538}},
}
}
func innerSolarToLunarNanBeiChao(date Time) Time {
year := date.solarTime.Year()
month := int(date.solarTime.Month())
day := date.solarTime.Day()
if year >= 384 && year <= 417 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, houQinCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
comment: "",
ganzhiMonth: ganzhiMonth,
eras: innerEras(lyear, houQinEras),
})
}
if year >= 398 && year <= 589 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, weiZhouSuiCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
comment: "",
ganzhiMonth: ganzhiMonth,
eras: innerEras(lyear, weiZhouSuiEras),
})
}
if year >= 397 && year <= 439 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, beiLiangCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
ganzhiMonth: ganzhiMonth,
desc: ldesc,
comment: "",
eras: innerEras(lyear, beiLiangEras),
})
}
if year >= 534 && year <= 577 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, dongWeiBeiQiCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
ganzhiMonth: ganzhiMonth,
comment: "",
eras: innerEras(lyear, dongWeiBeiQiEras),
})
}
return date
}

126
calendar/chineseNanMing.go Normal file
View File

@ -0,0 +1,126 @@
package calendar
func nanMingCals() map[int]uint32 {
return map[int]uint32{
1645: 1232804864,
1646: 1232088832,
1647: 1689265152,
1648: 1783732480,
1649: 3662686720,
1650: 1800249344,
1651: 1456485120,
1652: 719333632,
1653: 2465438976,
1654: 2464165888,
1655: 3378521344,
1656: 3567950336,
1657: 3567266816,
1658: 3662684416,
1659: 1520998144,
1660: 1453337088,
1661: 2799508992,
1662: 634401280,
1663: 2463115008,
1664: 2841320448,
1665: 2840604160,
1666: 3030393600,
1667: 3042056192,
1668: 2907712256,
1669: 1437474816,
1670: 1269838592,
1671: 632301824,
1672: 1388060160,
1673: 1387278336,
1674: 1689265408,
1675: 1957370368,
1676: 1788882176,
1677: 2907709696,
1678: 1302927104,
1679: 1264593408,
1680: 2775916288,
1681: 2766156032,
1682: 3529516544,
1683: 3912440576,
}
}
func nanMingEras01() []Era {
return []Era{
{
Year: 1646,
Emperor: "南明鲁王",
OtherNianHaoStart: "鲁王监国",
Dynasty: "南明",
},
{
Year: 1645,
Emperor: "南明隆武帝",
OtherNianHaoStart: "隆武",
Dynasty: "南明",
}, {
Year: 1645,
Emperor: "南明弘光帝",
Nianhao: "弘光",
Dynasty: "南明",
},
{
Year: 1628,
Emperor: "明思宗",
Nianhao: "崇祯",
Dynasty: "明",
},
}
}
func nanMingEras02() []Era {
return []Era{
{
Year: 1647,
Emperor: "南明/明郑",
OtherNianHaoStart: "永历",
Dynasty: "南明",
},
}
}
func nanMingEraMap() map[string][][]int {
return map[string][][]int{
"永历": [][]int{{1647, 1683}},
"鲁王监国": [][]int{{1646, 1653}},
"隆武": [][]int{{1645, 1646}},
"弘光": [][]int{{1645, 1645}},
}
}
func innerSolarToLunarNanMing(date Time) Time {
year := date.solarTime.Year()
month := int(date.solarTime.Month())
day := date.solarTime.Day()
if year > 1644 && year < 1654 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, nanMingCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
ganzhiMonth: ganzhiMonth,
comment: "",
eras: innerEras(lyear, nanMingEras01),
})
}
if year > 1646 && year < 1684 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, nanMingCals)
date.lunars = append(date.lunars, LunarTime{
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
ganzhiMonth: ganzhiMonth,
comment: "",
eras: innerEras(lyear, nanMingEras02),
})
}
return date
}

305
calendar/chineseSanGuo.go Normal file
View File

@ -0,0 +1,305 @@
package calendar
// 蜀汉朔日表
func shuCals() map[int]uint32 {
return map[int]uint32{
237: 2862623744,
238: 3042255104,
239: 2874160128,
240: 1432365568,
241: 2863373824,
242: 1788883200,
243: 2907710976,
244: 1432984576,
245: 1431318016,
246: 1789764352,
247: 1520449024,
248: 2865769216,
249: 1432100864,
250: 1431319296,
251: 1520445440,
252: 2865929472,
253: 2863673088,
254: 1431315712,
255: 1520998912,
256: 1453337856,
257: 2863964416,
258: 2862625792,
259: 3041929472,
260: 1454087936,
261: 1432367360,
262: 2862622208,
263: 3578927872,
}
}
func shuEras() []Era {
return []Era{
{
Year: 264,
Emperor: "魏元帝",
OtherNianHaoStart: "咸熙",
},
{
Year: 263,
Emperor: "蜀后主",
OtherNianHaoStart: "炎兴",
},
{
Year: 258,
Emperor: "蜀后主",
Nianhao: "景耀",
},
{
Year: 238,
Emperor: "蜀后主",
Nianhao: "延熙",
},
{
Year: 223,
Emperor: "蜀后主",
OtherNianHaoStart: "建兴",
},
{
Year: 221,
Emperor: "蜀昭烈帝",
Nianhao: "章武",
},
}
}
func shuEraMap() map[string][][]int {
return map[string][][]int{
"炎兴": [][]int{{263, 263}},
"景耀": [][]int{{258, 263}},
"延熙": [][]int{{238, 257}},
"建兴": [][]int{{223, 237}},
"章武": [][]int{{221, 223}},
}
}
func wuCals() map[int]uint32 {
return map[int]uint32{
223: 1432367360,
224: 2862622208,
225: 3578927616,
226: 2907712768,
227: 1433281280,
228: 1431320064,
229: 1788881408,
230: 2907971328,
231: 2865771008,
232: 1431316480,
233: 1789565952,
234: 1520447232,
235: 2865767424,
236: 1431378432,
237: 3578800896,
238: 1521295616,
239: 1436562432,
240: 2862622976,
241: 3578993920,
242: 3041931264,
243: 1436558848,
244: 2863766272,
245: 2862624000,
246: 3042320896,
247: 2865771776,
248: 1431317248,
249: 2863406848,
250: 1788883456,
251: 2874156800,
252: 1431969024,
253: 1431318272,
254: 1520444416,
255: 2874185984,
256: 2863672320,
257: 1431642368,
258: 3041932032,
259: 1453336832,
260: 2863898112,
261: 2862624768,
262: 3041928448,
263: 1453955840,
264: 1432366592,
265: 2863505920,
266: 1788884224,
267: 2907712000,
268: 1433149440,
269: 1431319040,
270: 1788880640,
271: 2907872256,
272: 2865770240,
273: 1431315456,
274: 1789434112,
275: 1453337600,
276: 2866094336,
277: 2862625536,
278: 3578800128,
279: 1454087680,
280: 1436561664,
}
}
func wuEraMap() map[string][][]int {
return map[string][][]int{
"天玺": [][]int{{276, 276}},
"天册": [][]int{{275, 276}},
"凤凰": [][]int{{272, 275}},
"建衡": [][]int{{269, 271}},
"宝鼎": [][]int{{266, 269}},
"甘露": [][]int{{265, 266}},
"元兴": [][]int{{264, 265}},
"永安": [][]int{{258, 264}},
"太平": [][]int{{256, 258}},
"五凤": [][]int{{254, 256}},
"建兴": [][]int{{252, 253}},
"太元": [][]int{{251, 252}},
"赤乌": [][]int{{238, 251}},
"嘉禾": [][]int{{232, 238}},
"黄龙": [][]int{{229, 231}},
"黄武": [][]int{{222, 229}},
}
}
func wuEras() []Era {
return []Era{
{
Year: 277,
Emperor: "吴末帝",
Nianhao: "天纪",
Dynasty: "吴",
},
{
Year: 276,
Emperor: "吴末帝",
OtherNianHaoStart: "天玺",
Dynasty: "吴",
},
{
Year: 275,
Emperor: "吴末帝",
OtherNianHaoStart: "天册",
Dynasty: "吴",
},
{
Year: 272,
Emperor: "吴末帝",
Nianhao: "凤凰",
Dynasty: "吴",
},
{
Year: 269,
Emperor: "吴末帝",
OtherNianHaoStart: "建衡",
Dynasty: "吴",
},
{
Year: 266,
Emperor: "吴末帝",
OtherNianHaoStart: "宝鼎",
Dynasty: "吴",
},
{
Year: 265,
Emperor: "吴末帝",
OtherNianHaoStart: "甘露",
Dynasty: "吴",
},
{
Year: 264,
Emperor: "吴末帝",
OtherNianHaoStart: "元兴",
Dynasty: "吴",
},
{
Year: 258,
Emperor: "吴景帝",
OtherNianHaoStart: "永安",
Dynasty: "吴",
},
{
Year: 256,
Emperor: "吴景帝",
OtherNianHaoStart: "太平",
Dynasty: "吴",
},
{
Year: 254,
Emperor: "吴景帝",
Nianhao: "五凤",
Dynasty: "吴",
},
{
Year: 252,
Emperor: "吴景帝",
OtherNianHaoStart: "建兴",
Dynasty: "吴",
},
{
Year: 251,
Emperor: "吴大帝",
OtherNianHaoStart: "太元",
Dynasty: "吴",
},
{
Year: 238,
Emperor: "吴大帝",
OtherNianHaoStart: "赤乌",
Dynasty: "吴",
},
{
Year: 232,
Emperor: "吴大帝",
Nianhao: "嘉禾",
Dynasty: "吴",
},
{
Year: 229,
Emperor: "吴大帝",
OtherNianHaoStart: "黄龙",
Dynasty: "吴",
},
{
Year: 222,
Emperor: "吴大帝",
Nianhao: "黄武",
Dynasty: "吴",
},
}
}
func innerSolarToLunarSanGuo(date Time) Time {
year := date.solarTime.Year()
month := int(date.solarTime.Month())
day := date.solarTime.Day()
if year >= 221 && year <= 263 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, shuCals)
date.lunars = append(date.lunars, LunarTime{
solarDate: date.solarTime,
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
comment: "",
ganzhiMonth: ganzhiMonth,
eras: innerEras(lyear, shuEras),
})
}
if year >= 222 && year <= 280 {
lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, 0, wuCals)
date.lunars = append(date.lunars, LunarTime{
solarDate: date.solarTime,
year: lyear,
month: lmonth,
day: lday,
leap: isLeap,
desc: ldesc,
ganzhiMonth: ganzhiMonth,
comment: "",
eras: innerEras(lyear, wuEras),
})
}
return date
}

View File

@ -7,16 +7,20 @@ import (
) )
type lunarSolar struct { type lunarSolar struct {
Lyear int Lyear int
Lmonth int Lmonth int
Lday int Lday int
Leap bool Leap bool
Year int Year int
Month int Month int
Day int Day int
Desc string
GanZhiYear string
GanZhiMonth string
GanZhiDay string
} }
func Test_ChineseCalendar(t *testing.T) { func Test_ChineseCalendarModern(t *testing.T) {
var testData = []lunarSolar{ var testData = []lunarSolar{
{Lyear: 1995, Lmonth: 12, Lday: 12, Leap: false, Year: 1996, Month: 1, Day: 31}, {Lyear: 1995, Lmonth: 12, Lday: 12, Leap: false, Year: 1996, Month: 1, Day: 31},
{Lyear: 2034, Lmonth: 1, Lday: 1, Leap: false, Year: 2034, Month: 2, Day: 19}, {Lyear: 2034, Lmonth: 1, Lday: 1, Leap: false, Year: 2034, Month: 2, Day: 19},
@ -40,7 +44,7 @@ func Test_ChineseCalendar(t *testing.T) {
for _, v := range testData { for _, v := range testData {
{ {
var lyear int = v.Year var lyear int = v.Year
lmonth, lday, leap, desp := SolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local)) _, lmonth, lday, leap, desp := Lunar(v.Year, v.Month, v.Day, 8.0)
if lmonth > v.Month { if lmonth > v.Month {
lyear-- lyear--
} }
@ -49,26 +53,223 @@ func Test_ChineseCalendar(t *testing.T) {
t.Fatal(v, lyear, lmonth, lday, leap, desp) t.Fatal(v, lyear, lmonth, lday, leap, desp)
} }
date := LunarToSolar(v.Lyear, v.Lmonth, v.Lday, v.Leap) date := Solar(v.Lyear, v.Lmonth, v.Lday, v.Leap, 8.0)
if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day { if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day {
t.Fatal(v, date) t.Fatal(v, date)
} }
} }
{ /*
var lyear int = v.Year {
lmonth, lday, leap, desp := RapidSolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local)) var lyear int = v.Year
if lmonth > v.Month { lmonth, lday, leap, desp := RapidSolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local))
lyear-- if lmonth > v.Month {
lyear--
}
fmt.Println(lyear, desp, v.Year, v.Month, v.Day)
if lyear != v.Lyear || lmonth != v.Lmonth || lday != v.Lday || leap != v.Leap {
t.Fatal(v, lyear, lmonth, lday, leap, desp)
}
date := RapidLunarToSolar(v.Lyear, v.Lmonth, v.Lday, v.Leap)
if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day {
t.Fatal(v, date)
}
} }
fmt.Println(lyear, desp, v.Year, v.Month, v.Day) */
if lyear != v.Lyear || lmonth != v.Lmonth || lday != v.Lday || leap != v.Leap { }
t.Fatal(v, lyear, lmonth, lday, leap, desp) }
func Test_ChineseCalendarModern2(t *testing.T) {
var testData = []lunarSolar{
{Lyear: 1995, Lmonth: 12, Lday: 12, Leap: false, Year: 1996, Month: 1, Day: 31},
{Lyear: 2034, Lmonth: 1, Lday: 1, Leap: false, Year: 2034, Month: 2, Day: 19},
{Lyear: 2033, Lmonth: 12, Lday: 30, Leap: false, Year: 2034, Month: 2, Day: 18},
{Lyear: 2033, Lmonth: 11, Lday: 27, Leap: true, Year: 2034, Month: 1, Day: 17},
{Lyear: 2033, Lmonth: 11, Lday: 1, Leap: true, Year: 2033, Month: 12, Day: 22},
{Lyear: 2033, Lmonth: 11, Lday: 30, Leap: false, Year: 2033, Month: 12, Day: 21},
{Lyear: 2023, Lmonth: 2, Lday: 30, Leap: false, Year: 2023, Month: 3, Day: 21},
{Lyear: 2023, Lmonth: 2, Lday: 1, Leap: true, Year: 2023, Month: 3, Day: 22},
{Lyear: 2020, Lmonth: 1, Lday: 1, Leap: false, Year: 2020, Month: 1, Day: 25},
{Lyear: 2015, Lmonth: 1, Lday: 1, Leap: false, Year: 2015, Month: 2, Day: 19},
{Lyear: 2014, Lmonth: 12, Lday: 30, Leap: false, Year: 2015, Month: 2, Day: 18},
{Lyear: 1996, Lmonth: 1, Lday: 1, Leap: false, Year: 1996, Month: 2, Day: 19},
{Lyear: 1995, Lmonth: 12, Lday: 30, Leap: false, Year: 1996, Month: 2, Day: 18},
{Lyear: 1996, Lmonth: 10, Lday: 30, Leap: false, Year: 1996, Month: 12, Day: 10},
{Lyear: 2014, Lmonth: 9, Lday: 1, Leap: true, Year: 2014, Month: 10, Day: 24},
{Lyear: 2014, Lmonth: 9, Lday: 30, Leap: false, Year: 2014, Month: 10, Day: 23},
{Lyear: 2014, Lmonth: 10, Lday: 1, Leap: false, Year: 2014, Month: 11, Day: 22},
{Lyear: 2021, Lmonth: 12, Lday: 29, Leap: false, Year: 2022, Month: 1, Day: 31},
}
for _, v := range testData {
{
res, err := SolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local))
if err != nil {
t.Fatal(err)
}
if len(res.Lunars()) != 1 {
t.Fatal("len(res.Lunars())!=1")
}
lunar := res.Lunars()[0]
if lunar.year != v.Lyear || lunar.month != v.Lmonth || lunar.day != v.Lday || lunar.leap != v.Leap {
t.Fatal(v, lunar.year, lunar.month, lunar.day, lunar.leap)
} }
date := RapidLunarToSolar(v.Lyear, v.Lmonth, v.Lday, v.Leap) date, err := LunarToSolarSingle(v.Lyear, v.Lmonth, v.Lday, v.Leap)
if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day { if err != nil {
t.Fatal(err)
}
solar := date.Time()
if solar.Year() != v.Year || int(solar.Month()) != v.Month || solar.Day() != v.Day {
t.Fatal(v, date) t.Fatal(v, date)
} }
} }
/*
{
var lyear int = v.Year
lmonth, lday, leap, desp := RapidSolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local))
if lmonth > v.Month {
lyear--
}
fmt.Println(lyear, desp, v.Year, v.Month, v.Day)
if lyear != v.Lyear || lmonth != v.Lmonth || lday != v.Lday || leap != v.Leap {
t.Fatal(v, lyear, lmonth, lday, leap, desp)
}
date := RapidLunarToSolar(v.Lyear, v.Lmonth, v.Lday, v.Leap)
if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day {
t.Fatal(v, date)
}
}
*/
}
}
func Test_ChineseCalendarAncient(t *testing.T) {
var testData = []lunarSolar{
{Lyear: -103, Lmonth: 1, Lday: 1, Leap: false, Year: -103, Month: 2, Day: 22, Desc: "太初元年正月初一", GanZhiYear: "丁丑", GanZhiMonth: "壬寅", GanZhiDay: "癸亥"},
{Lyear: -101, Lmonth: 6, Lday: 2, Leap: true, Year: -101, Month: 7, Day: 28, Desc: "太初三年闰六月初二", GanZhiYear: "己卯", GanZhiMonth: "辛未", GanZhiDay: "己酉"},
{Lyear: 8, Lmonth: 11, Lday: 29, Leap: false, Year: 9, Month: 1, Day: 14, Desc: "初始元年冬月廿九", GanZhiYear: "戊辰", GanZhiMonth: "甲子", GanZhiDay: "壬申"},
//王莽改制
{Lyear: 9, Lmonth: 1, Lday: 1, Leap: false, Year: 9, Month: 1, Day: 15, Desc: "始建国元年正月初一", GanZhiYear: "己巳", GanZhiMonth: "乙丑", GanZhiDay: "癸酉"},
{Lyear: 23, Lmonth: 1, Lday: 1, Leap: false, Year: 23, Month: 1, Day: 11, Desc: "地皇四年正月初一", GanZhiYear: "癸未", GanZhiMonth: "癸丑", GanZhiDay: "壬午"},
{Lyear: 23, Lmonth: 2, Lday: 1, Leap: false, Year: 23, Month: 2, Day: 10, Desc: "地皇四年二月初一", GanZhiYear: "癸未", GanZhiMonth: "甲寅", GanZhiDay: "壬子"},
//改回来了
{Lyear: 23, Lmonth: 1, Lday: 1, Leap: false, Year: 23, Month: 2, Day: 10, Desc: "更始元年正月初一", GanZhiYear: "癸未", GanZhiMonth: "甲寅", GanZhiDay: "壬子"},
{Lyear: 23, Lmonth: 12, Lday: 1, Leap: false, Year: 23, Month: 12, Day: 31, Desc: "更始元年腊月初一", GanZhiYear: "癸未", GanZhiMonth: "乙丑", GanZhiDay: "丙子"},
{Lyear: 24, Lmonth: 1, Lday: 1, Leap: false, Year: 24, Month: 1, Day: 30, Desc: "更始二年正月初一", GanZhiYear: "甲申", GanZhiMonth: "丙寅", GanZhiDay: "丙午"},
{Lyear: 97, Lmonth: 8, Lday: 5, Leap: true, Year: 97, Month: 9, Day: 29, Desc: "永元九年闰八月初五", GanZhiYear: "丁酉", GanZhiMonth: "己酉", GanZhiDay: "壬申"},
{Lyear: 100, Lmonth: 2, Lday: 1, Leap: false, Year: 100, Month: 2, Day: 28, Desc: "永元十二年二月初一", GanZhiYear: "庚子", GanZhiMonth: "己卯", GanZhiDay: "甲寅"},
//按照儒略历这一天有29号
{Lyear: 100, Lmonth: 2, Lday: 3, Leap: false, Year: 100, Month: 3, Day: 1, Desc: "永元十二年二月初三", GanZhiYear: "庚子", GanZhiMonth: "己卯", GanZhiDay: "丙辰"},
//三国演义
{Lyear: 190, Lmonth: 1, Lday: 1, Leap: false, Year: 190, Month: 2, Day: 23, Desc: "初平元年正月初一", GanZhiYear: "庚午", GanZhiMonth: "戊寅", GanZhiDay: "壬寅"},
{Lyear: 220, Lmonth: 5, Lday: 5, Leap: false, Year: 220, Month: 6, Day: 23, Desc: "黄初元年五月初五", GanZhiYear: "庚子", GanZhiMonth: "壬午", GanZhiDay: "庚辰"},
{Lyear: 220, Lmonth: 5, Lday: 5, Leap: false, Year: 220, Month: 6, Day: 23, Desc: "建安二十五年五月初五", GanZhiYear: "庚子", GanZhiMonth: "壬午", GanZhiDay: "庚辰"},
{Lyear: 220, Lmonth: 5, Lday: 5, Leap: false, Year: 220, Month: 6, Day: 23, Desc: "延康元年五月初五", GanZhiYear: "庚子", GanZhiMonth: "壬午", GanZhiDay: "庚辰"},
{Lyear: 246, Lmonth: 12, Lday: 2, Leap: true, Year: 247, Month: 1, Day: 25, Desc: "正始七年闰腊月初二", GanZhiYear: "丙寅", GanZhiMonth: "辛丑", GanZhiDay: "壬申"},
{Lyear: 246, Lmonth: 12, Lday: 2, Leap: false, Year: 247, Month: 1, Day: 25, Desc: "延熙九年腊月初二", GanZhiYear: "丙寅", GanZhiMonth: "辛丑", GanZhiDay: "壬申"},
{Lyear: 237, Lmonth: 2, Lday: 29, Leap: false, Year: 237, Month: 4, Day: 11, Desc: "景初元年二月廿九", GanZhiYear: "丁巳", GanZhiMonth: "癸卯", GanZhiDay: "丙申"},
{Lyear: 237, Lmonth: 4, Lday: 1, Leap: false, Year: 237, Month: 4, Day: 12, Desc: "景初元年四月初一", GanZhiYear: "丁巳", GanZhiMonth: "甲辰", GanZhiDay: "丁酉"},
{Lyear: 237, Lmonth: 2, Lday: 29, Leap: false, Year: 237, Month: 4, Day: 12, Desc: "建兴十五年二月廿九", GanZhiYear: "丁巳", GanZhiMonth: "癸卯", GanZhiDay: "丁酉"},
{Lyear: 237, Lmonth: 2, Lday: 30, Leap: false, Year: 237, Month: 4, Day: 12, Desc: "嘉禾六年二月三十", GanZhiYear: "丁巳", GanZhiMonth: "癸卯", GanZhiDay: "丁酉"},
//魏明帝改制导致景初三年有两个12月
{Lyear: 239, Lmonth: 12, Lday: 1, Leap: false, Year: 239, Month: 12, Day: 13, Desc: "景初三年腊月初一", GanZhiYear: "己未", GanZhiMonth: "丙子", GanZhiDay: "壬子"},
{Lyear: 239, Lmonth: 12, Lday: 1, Leap: false, Year: 240, Month: 1, Day: 12, Desc: "景初三年腊月初一", GanZhiYear: "己未", GanZhiMonth: "丁丑", GanZhiDay: "壬午"},
//武则天改制,建子为正月,但是其他月份不变,所以正月不是一月,一月相当于三月,以此类推
{Lyear: 690, Lmonth: 1, Lday: 1, Leap: false, Year: 689, Month: 12, Day: 18, Desc: "天授元年正月初一", GanZhiYear: "庚寅", GanZhiMonth: "丙子", GanZhiDay: "庚辰"},
{Lyear: 690, Lmonth: 1, Lday: 1, Leap: false, Year: 689, Month: 12, Day: 18, Desc: "载初元年正月初一", GanZhiYear: "庚寅", GanZhiMonth: "丙子", GanZhiDay: "庚辰"},
// 太抽象了,一月是一月,正月是正月。一月!=正月
{Lyear: 690, Lmonth: 3, Lday: 1, Leap: false, Year: 690, Month: 2, Day: 15, Desc: "天授元年一月初一", GanZhiYear: "庚寅", GanZhiMonth: "戊寅", GanZhiDay: "己卯"},
{Lyear: 700, Lmonth: 2, Lday: 6, Leap: false, Year: 700, Month: 1, Day: 1, Desc: "圣历三年腊月初六", GanZhiYear: "庚子", GanZhiMonth: "丁丑", GanZhiDay: "丙戌"},
{Lyear: 700, Lmonth: 12, Lday: 6, Leap: false, Year: 701, Month: 1, Day: 19, Desc: "圣历三年腊月初六", GanZhiYear: "庚子", GanZhiMonth: "己丑", GanZhiDay: "庚戌"},
{Lyear: 700, Lmonth: 11, Lday: 1, Leap: false, Year: 700, Month: 12, Day: 15, Desc: "圣历三年冬月初一", GanZhiYear: "庚子", GanZhiMonth: "戊子", GanZhiDay: "乙亥"},
//格里高利历改革
{Lyear: 1582, Lmonth: 9, Lday: 18, Leap: false, Year: 1582, Month: 10, Day: 4, Desc: "万历十年九月十八", GanZhiYear: "壬午", GanZhiMonth: "庚戌", GanZhiDay: "癸酉"},
{Lyear: 1582, Lmonth: 9, Lday: 19, Leap: false, Year: 1582, Month: 10, Day: 15, Desc: "万历十年九月十九", GanZhiYear: "壬午", GanZhiMonth: "庚戌", GanZhiDay: "甲戌"},
{Lyear: 1631, Lmonth: 11, Lday: 10, Leap: true, Year: 1632, Month: 1, Day: 1, Desc: "崇祯四年闰冬月初十", GanZhiYear: "辛未", GanZhiMonth: "庚子", GanZhiDay: "己酉"},
{Lyear: 1912, Lmonth: 11, Lday: 24, Leap: false, Year: 1913, Month: 1, Day: 1, Desc: "一九一二年冬月廿四", GanZhiYear: "壬子", GanZhiMonth: "壬子", GanZhiDay: "壬午"},
}
for _, v := range testData {
{
dates, err := SolarToLunar(time.Date(v.Year, time.Month(v.Month), v.Day, 0, 0, 0, 0, time.Local))
if err != nil {
t.Fatal(err)
}
succ := false
for _, date := range dates.Lunars() {
for _, v2 := range date.LunarDesc() {
if v2 == v.Desc {
succ = true
if date.LunarYear() != v.Lyear || date.LunarMonth() != v.Lmonth || date.LunarDay() != v.Lday || date.IsLeap() != v.Leap {
t.Fatal(v, date.LunarYear(), date.LunarMonth(), date.LunarDay(), date.IsLeap())
}
if date.solarDate.IsZero() {
t.Fatal(v, "zero")
}
if date.GanZhiYear() != v.GanZhiYear || date.GanZhiMonth() != v.GanZhiMonth || date.GanZhiDay() != v.GanZhiDay {
t.Fatal(v, date.GanZhiYear(), date.GanZhiMonth(), date.GanZhiDay())
}
break
}
}
}
if !succ {
t.Fatal("not found", v, dates.LunarDesc(), dates.LunarInfo())
}
}
{
dates, err := LunarToSolar(v.Desc)
if err != nil {
t.Fatal(err)
}
succ := false
for _, date := range dates {
solar := date.Solar()
if solar.Year() == v.Year && int(solar.Month()) == v.Month && solar.Day() == v.Day {
succ = true
break
}
}
if !succ {
t.Fatal("not found", v, dates)
}
}
} }
} }
func TestGanZhiOfDay(t *testing.T) {
dates := time.Date(23, 12, 31, 0, 0, 0, 0, time.Local)
fmt.Println(SolarToLunar(dates))
//date, err := LunarToSolar("久视元年腊月辛亥")
date, err := LunarToSolar("万历十年九月甲戌")
if err != nil {
t.Fatal(err)
}
for _, v := range date {
fmt.Println(v.solarTime)
fmt.Println(v.LunarDescWithDynastyAndEmperor())
}
}
/*
func TestgenReverseMapNianHao(t *testing.T) {
//mymap := make(map[string][][]int)
eras := nanMingEras01()
for idx, v := range eras {
if idx == 0 {
continue
}
end := (eras[idx-1].Year - eras[idx-1].Offset) - 1
if eras[idx-1].OtherNianHaoStart != "" {
end++
}
niaohao := v.Nianhao
if v.OtherNianHaoStart != "" {
niaohao = v.OtherNianHaoStart
}
fmt.Printf("\"%s\":[][]int{{%d,%d}},\n", niaohao, v.Year-v.Offset, end)
}
}
*/

2477
calendar/era.go Normal file

File diff suppressed because it is too large Load Diff

299
calendar/time.go Normal file
View File

@ -0,0 +1,299 @@
package calendar
import (
"time"
)
type LunarInfo struct {
// SolarDate 公历日期
SolarDate time.Time `json:"solarDate"`
// LunarYear 农历年的公历映射如2025
LunarYear int `json:"lunarYear"`
// LunarYearChn 农历年公历映射中文表示,比如二零二五
LunarYearChn string `json:"lunarYearChn"`
// LunarMonth 农历月表示以当时的历法推定的农历月与正月的距离正月为1二月为2依次类推
// 武则天改历时期正月为1, 十二月为2,一月为3二月为4,以此类推
LunarMonth int `json:"lunarMonth"`
// LunarDay 农历日,[1-30]
LunarDay int `json:"lunarDay"`
// IsLeap 是否闰月
IsLeap bool `json:"isLeap"`
// LunarMonthDayDesc 农历月日描述,如正月初一。此处,十一月表示为冬月,十二月表示为腊月
LunarMonthDayDesc string `json:"lunarMonthDayDesc"`
// GanzhiYear 农历年干支
GanzhiYear string `json:"ganzhiYear"`
// GanzhiMonth 农历月干支,闰月从上一个月
GanzhiMonth string `json:"ganzhiMonth"`
// GanzhiDay 农历日干支
GanzhiDay string `json:"ganzhiDay"`
// Dynasty 朝代,如唐、宋、元、明、清等
Dynasty string `json:"dynasty"`
// Emperor 皇帝姓名(仅供参考,多个皇帝用同一个年号的场景,此处不准)
Emperor string `json:"emperor"`
// Nianhao 年号 如"开元"
Nianhao string `json:"nianhao"`
// YearOfNianhao 该年号的第几年
YearOfNianhao int `json:"yearOfNianhao"`
// EraDesc 年代描述,如唐玄宗开元二年
EraDesc string `json:"eraDesc"`
// LunarWithEraDesc 农历日期加上年代描述,如开元二年正月初一
LunarWithEraDesc string `json:"lunarWithNianhaoDesc"`
// ChineseZodiac 生肖
ChineseZodiac string `json:"chineseZodiac"`
}
type Time struct {
solarTime time.Time
lunars []LunarTime
}
func (t Time) Solar() time.Time {
return t.solarTime
}
func (t Time) Time() time.Time {
return t.solarTime
}
func (t Time) Lunars() []LunarTime {
return t.lunars
}
func (t Time) LunarDesc() []string {
var res []string
for _, v := range t.lunars {
res = append(res, v.LunarDesc()...)
}
return res
}
func (t Time) LunarDescWithEmperor() []string {
var res []string
for _, v := range t.lunars {
res = append(res, v.LunarDescWithEmperor()...)
}
return res
}
func (t Time) LunarDescWithDynasty() []string {
var res []string
for _, v := range t.lunars {
res = append(res, v.LunarDescWithDynasty()...)
}
return res
}
func (t Time) LunarDescWithDynastyAndEmperor() []string {
var res []string
for _, v := range t.lunars {
res = append(res, v.LunarDescWithDynastyAndEmperor()...)
}
return res
}
func (t Time) LunarInfo() []LunarInfo {
var res []LunarInfo
for _, v := range t.lunars {
res = append(res, v.LunarInfo()...)
}
return res
}
func (t Time) Eras() []EraDesc {
var res []EraDesc
for _, v := range t.lunars {
res = append(res, v.eras...)
}
return res
}
func (t Time) Lunar() LunarTime {
if len(t.lunars) > 0 {
return t.lunars[0]
}
return LunarTime{}
}
func (t Time) Add(d time.Duration) Time {
if d < time.Second {
newT := t.solarTime.Add(d)
rT, _ := SolarToLunar(newT)
return rT
}
sec := d.Seconds()
jde := Date2JDE(t.solarTime)
jde += sec / 86400.0
newT := JDE2Date(jde)
rT, _ := SolarToLunar(newT)
return rT
}
type LunarTime struct {
solarDate time.Time
//农历年
year int
//农历月表示以当时的历法推定的农历月与正月的距离正月为1二月为2依次类推闰月显示所闰月
month int
//农历日
day int
//是否闰月
leap bool
//农历描述
desc string
//备注
comment string
//ganzhi of month 月干支
ganzhiMonth string
eras []EraDesc
}
// ShengXiao 生肖
func (l LunarTime) ShengXiao() string {
shengxiao := []string{"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"}
diff := l.LunarYear() % 12
if diff < 0 {
diff += 12
}
return shengxiao[diff]
}
// Zodiac 生肖,和生肖同义
func (l LunarTime) Zodiac() string {
return l.ShengXiao()
}
// GanZhiYear 年干支
func (l LunarTime) GanZhiYear() string {
return GanZhiOfYear(l.year)
}
// GanZhiMonth 月干支
func (l LunarTime) GanZhiMonth() string {
return l.ganzhiMonth
}
// GanZhiDay 日干支
func (l LunarTime) GanZhiDay() string {
return GanZhiOfDay(l.solarDate)
}
// LunarYear 农历年
func (l LunarTime) LunarYear() int {
return l.year
}
// LunarMonth 农历月
func (l LunarTime) LunarMonth() int {
return l.month
}
// LunarDay 农历日
func (l LunarTime) LunarDay() int {
return l.day
}
// IsLeap 是否闰月
func (l LunarTime) IsLeap() bool {
return l.leap
}
// Eras 朝代、皇帝、年号等信息
func (l LunarTime) Eras() []EraDesc {
return l.eras
}
// MonthDay 农历月日描述,如正月初一。此处,十一月表示为冬月,十二月表示为腊月
func (l LunarTime) MonthDay() string {
return l.desc
}
// LunarDesc 获取农历描述,如开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
func (l LunarTime) LunarDesc() []string {
return l.innerDescWithNianHao(false, false)
}
// LunarDescWithEmperor 获取含有君主信息的农历描述,如唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// 君主信息仅供参考,多个皇帝用同一个年号的场景,此处不准
func (l LunarTime) LunarDescWithEmperor() []string {
return l.innerDescWithNianHao(true, false)
}
// LunarDescWithDynasty 获取含有朝代信息的农历描述,如唐 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
func (l LunarTime) LunarDescWithDynasty() []string {
return l.innerDescWithNianHao(false, true)
}
// LunarDescWithDynastyAndEmperor 获取含有朝代和君主信息的农历描述,如唐 唐玄宗 开元二年正月初一,若无年号,则返回年份描述,如二零二五年正月初一
// 君主信息仅供参考,多个皇帝用同一个年号的场景,此处不准
func (l LunarTime) LunarDescWithDynastyAndEmperor() []string {
return l.innerDescWithNianHao(true, true)
}
func (l LunarTime) innerDescWithNianHao(withEmperor bool, withDynasty bool) []string {
var res []string
if len(l.eras) > 0 {
for _, v := range l.eras {
tmp := v.String() + l.desc
if withEmperor {
tmp = v.Emperor + " " + tmp
}
if withDynasty {
tmp = v.Dynasty + " " + tmp
}
res = append(res, tmp)
}
} else {
res = append(res, number2Chinese(l.year, true)+"年"+l.desc)
}
return res
}
func (l LunarTime) LunarInfo() []LunarInfo {
var res []LunarInfo
for _, v := range l.eras {
li := LunarInfo{
SolarDate: l.solarDate,
LunarYear: l.year,
LunarYearChn: number2Chinese(l.year, true),
LunarMonth: l.month,
LunarDay: l.day,
IsLeap: l.leap,
LunarMonthDayDesc: l.desc,
GanzhiYear: GanZhiOfYear(l.year),
GanzhiMonth: l.ganzhiMonth,
GanzhiDay: GanZhiOfDay(l.solarDate),
Dynasty: v.Dynasty,
Emperor: v.Emperor,
Nianhao: v.Nianhao,
YearOfNianhao: v.YearOfNianHao,
EraDesc: v.String(),
LunarWithEraDesc: v.String() + l.desc,
ChineseZodiac: l.ShengXiao(),
}
res = append(res, li)
}
if len(l.eras) == 0 {
li := LunarInfo{
SolarDate: l.solarDate,
LunarYear: l.year,
LunarYearChn: number2Chinese(l.year, true),
LunarMonth: l.month,
LunarDay: l.day,
IsLeap: l.leap,
LunarMonthDayDesc: l.desc,
GanzhiYear: GanZhiOfYear(l.year),
GanzhiMonth: l.ganzhiMonth,
GanzhiDay: GanZhiOfDay(l.solarDate),
Dynasty: "",
Emperor: "",
Nianhao: "",
YearOfNianhao: 0,
EraDesc: number2Chinese(l.year, true) + "年",
LunarWithEraDesc: number2Chinese(l.year, true) + "年" + l.desc,
ChineseZodiac: l.ShengXiao(),
}
res = append(res, li)
}
return res
}

View File

@ -1,6 +1,7 @@
package moon package moon
import ( import (
"b612.me/astro/tools"
"errors" "errors"
"math" "math"
"time" "time"
@ -201,7 +202,7 @@ func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, er
if aero { if aero {
aeroFloat = 1 aeroFloat = 1
} }
downJde := basic.GetMoonDownTime(jde, lon, lat, timezone, aeroFloat, height) downJde := basic.GetMoonSetTime(jde, lon, lat, timezone, aeroFloat, height)
if downJde == -3 { if downJde == -3 {
err = ERR_NOT_TODAY err = ERR_NOT_TODAY
} }
@ -214,6 +215,41 @@ func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, er
return basic.JDE2DateByZone(downJde, date.Location(), true), err return basic.JDE2DateByZone(downJde, date.Location(), true), err
} }
// SunMoonLoDiff 日月黄经差新月时为0满月时为180
// 取值范围[0,360)
func SunMoonLoDiff(date time.Time) float64 {
jde := basic.TD2UT(basic.Date2JDE(date.UTC()), true)
sunLo := basic.HSunApparentLo(jde)
moonLo := basic.HMoonApparentLo(jde)
return tools.Limit360(moonLo - sunLo)
}
// PhaseDesc 月相描述
// 返回Date对应UTC世界时的月相描述
// 取值范围:新月,上峨眉月,上弦月,盈凸月,满月,亏凸月,下弦月,下峨眉月,残月
func PhaseDesc(date time.Time) string {
moonSunLoDiff := SunMoonLoDiff(date)
if moonSunLoDiff >= 0 && moonSunLoDiff <= 30 {
return "新月"
} else if moonSunLoDiff > 30 && moonSunLoDiff <= 75 {
return "上峨眉月"
} else if moonSunLoDiff > 75 && moonSunLoDiff <= 135 {
return "上弦月"
} else if moonSunLoDiff > 135 && moonSunLoDiff < 170 {
return "盈凸月"
} else if moonSunLoDiff >= 170 && moonSunLoDiff <= 190 {
return "满月"
} else if moonSunLoDiff > 190 && moonSunLoDiff < 225 {
return "亏凸月"
} else if moonSunLoDiff >= 225 && moonSunLoDiff < 285 {
return "下弦月"
} else if moonSunLoDiff >= 285 && moonSunLoDiff < 330 {
return "下峨眉月"
} else {
return "残月"
}
}
// Phase 月相 // Phase 月相
// 返回Date对应UTC世界时的月相大小 // 返回Date对应UTC世界时的月相大小
func Phase(date time.Time) float64 { func Phase(date time.Time) float64 {

View File

@ -2,6 +2,7 @@ package sun
import ( import (
"errors" "errors"
"math"
"time" "time"
"b612.me/astro/basic" "b612.me/astro/basic"
@ -284,3 +285,27 @@ func EarthDistance(date time.Time) float64 {
jde = basic.TD2UT(jde, true) jde = basic.TD2UT(jde, true)
return basic.EarthAway(jde) return basic.EarthAway(jde)
} }
// ApparentSolarTime 真太阳时
// 返回给定经度lon的真太阳时
func ApparentSolarTime(date time.Time, lon float64) time.Time {
//真太阳时=太阳时角+12小时
trueTime := (HourAngle(date, lon, 0) + 180) / 15
if trueTime > 24 {
trueTime -= 24
}
//真太阳时的分
minute := (trueTime - math.Floor(trueTime)) * 60
//真太阳时的秒
second := (minute - math.Floor(minute)) * 60
//当地经度下的本地时区
trueSunTime := date.In(time.FixedZone("LTZ", int(lon*3600.00/15.0)))
if trueSunTime.Hour()-int(trueTime) > 12 {
trueSunTime = trueSunTime.Add(time.Hour * 24)
} else if int(trueTime)-trueSunTime.Hour() > 12 {
trueSunTime = trueSunTime.Add(-time.Hour * 24)
}
return time.Date(trueSunTime.Year(), trueSunTime.Month(), trueSunTime.Day(),
int(trueTime), int(minute), int(second), int((second-math.Floor(second))*1000000000),
time.FixedZone("LTZ", int(lon*3600.00/15.0)))
}