diff --git a/basic/all_test.go b/basic/all_test.go index 63426b6..bfca415 100644 --- a/basic/all_test.go +++ b/basic/all_test.go @@ -34,6 +34,6 @@ func show() { fmt.Print("农历:") fmt.Println(GetLunar(2019, 10, 23, 8.0/24.0)) 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)) } diff --git a/basic/calendar.go b/basic/calendar.go index 40917b6..51c0dbc 100644 --- a/basic/calendar.go +++ b/basic/calendar.go @@ -7,7 +7,7 @@ import ( "time" ) -var defDeltaTFn = DefaultDeltaT +var defDeltaTFn = DefaultDeltaTv2 /* @name: 儒略日计算 @@ -152,6 +152,93 @@ func DefaultDeltaT(Date float64, IsJDE bool) (Result float64) { //传入年或 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 世界时转力学时CC,false 力学时转世界时VV 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) } -func GetLunar(year, month, day int, tz float64) (lmonth, lday int, leap bool, result string) { - jde := JDECalc(year, month, float64(day)) //计算当前JDE时间 - if month == 11 || month == 12 { //判断当前日期属于前一年周期还是后一年周期 - //判断方法:当前日期与冬至日所在朔望月的关系 - 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 //下一朔月(世界时,北京时间) - if Fday-math.Floor(Fday) > 0.5 { - Fday = math.Floor(Fday) + 0.5 - } else { - Fday = math.Floor(Fday) - 0.5 +// Date2JDE 日期转儒略日 +func Date2JDE(date time.Time) float64 { + 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) +} + +func GetLunar(year, month, day int, tz float64) (adjustedYear, lmonth, lday int, leap bool, result string) { + julianDayEpoch := JDECalc(year, month, float64(day)) + // 确定农历年份 + adjustedYear = year + 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 { - Yday = math.Floor(Yday) + 0.5 - } else { - Yday = math.Floor(Yday) - 0.5 - } - if winterday >= Fday && winterday < Yday && jde <= Fday { - year-- - } - if winterday >= Yday && jde < Yday { - year-- + if winterSolsticeDay >= nextNewMoonDay && julianDayEpoch < nextNewMoonDay { + adjustedYear-- } } else { - year-- + adjustedYear-- } - jieqi := GetJieqiLoops(year, 25) //一年的节气 - moon := GetMoonLoops(float64(year), 17) //一年朔月日 - winter1 := jieqi[0] - 8.0/24 + tz //第一年冬至日 - winter2 := jieqi[24] - 8.0/24 + tz //第二年冬至日 - for idx, v := range moon { - if tz != 8.0/24 { - v = v - 8.0/24 + tz - } - if v-math.Floor(v) > 0.5 { - moon[idx] = math.Floor(v) + 0.5 - } else { - moon[idx] = math.Floor(v) - 0.5 - } - } //置闰月为0点 - for idx, v := range jieqi { - if tz != 8.0/24 { - 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 //最大最小计数 + + // 获取节气和朔望月数据 + solarTerms := GetJieqiLoops(adjustedYear, 25) + newMoonDays := GetMoonLoops(float64(adjustedYear), 17) + + // 计算冬至日期 + winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz + winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz + + // 规范化时间点 + normalizeTimeArray(newMoonDays, tz) + normalizeTimeArray(solarTerms, tz) + + // 计算朔望月范围 + minMoonIndex, maxMoonIndex := 20, 0 + moonCount := 0 for i := 0; i < 15; i++ { - if moon[i] >= winter1 && moon[i] < winter2 { - if i <= min { - min = i + if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond { + if i <= minMoonIndex { + minMoonIndex = i } - if i >= max { - max = i + if i >= maxMoonIndex { + maxMoonIndex = i } - mooncount++ + moonCount++ } } - leapmonth := 20 - if mooncount == 13 { //存在闰月 - var j, i = 2, 0 - for i = min; i <= max; i++ { - if !(moon[i] <= jieqi[j] && moon[i+1] > jieqi[j]) { + + // 确定闰月位置 + leapMonthPos := 20 + if moonCount == 13 { + solarTermIndex, i := 2, 0 + for i = minMoonIndex; i <= maxMoonIndex; i++ { + if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) { 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 } } - lmonth = i - min - var sleap bool = false + + // 计算农历月份 + lmonth = currentMoonIndex - minMoonIndex + shouldAdjustLeap := false leap = false - if lmonth >= leapmonth { - sleap = true + + if lmonth >= leapMonthPos { + shouldAdjustLeap = true } - if lmonth == leapmonth { + if lmonth == leapMonthPos { leap = true } if lmonth < 2 { @@ -337,102 +422,125 @@ func GetLunar(year, month, day int, tz float64) (lmonth, lday int, leap bool, re } else { lmonth-- } - if sleap { + if shouldAdjustLeap { lmonth-- } if lmonth <= 0 { lmonth += 12 } - lday = int(jde-moon[i-1]) + 1 - strmonth := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"} - strday := []string{"初", "十", "廿", "三"} - if leap { - result += "闰" - } - 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] - } + + // 计算农历日期 + lday = int(julianDayEpoch-newMoonDays[currentMoonIndex-1]) + 1 + + // 生成农历日期字符串 + result = formatLunarDateString(lmonth, lday, leap) + return } func GetSolar(year, month, day int, leap bool, tz float64) float64 { + adjustedYear := year if month < 11 { - year-- + adjustedYear-- } - jieqi := GetJieqiLoops(year, 25) //一年的节气 - moon := GetMoonLoops(float64(year), 17) //一年朔月日 - winter1 := jieqi[0] - 8.0/24 + tz //第一年冬至日 - winter2 := jieqi[24] - 8.0/24 + tz //第二年冬至日 - for idx, v := range moon { - if tz != 8.0/24 { - v = v - 8.0/24 + tz - } - if v-math.Floor(v) > 0.5 { - moon[idx] = math.Floor(v) + 0.5 - } else { - moon[idx] = math.Floor(v) - 0.5 - } - } //置闰月为0点 - for idx, v := range jieqi { - if tz != 8.0/24 { - 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 //最大最小计数 + + // 获取节气和朔望月数据 + solarTerms := GetJieqiLoops(adjustedYear, 25) + newMoonDays := GetMoonLoops(float64(adjustedYear), 17) + + // 计算冬至日期 + winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz + winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz + + // 规范化时间点 + normalizeTimeArray(newMoonDays, tz) + normalizeTimeArray(solarTerms, tz) + + // 计算朔望月范围 + minMoonIndex, maxMoonIndex := 20, 0 + moonCount := 0 for i := 0; i < 15; i++ { - if moon[i] >= winter1 && moon[i] < winter2 { - if i <= min { - min = i + if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond { + if i <= minMoonIndex { + minMoonIndex = i } - if i >= max { - max = i + if i >= maxMoonIndex { + maxMoonIndex = i } - mooncount++ + moonCount++ } } - leapmonth := 20 - if mooncount == 13 { //存在闰月 - var j, i = 2, 0 - for i = min; i <= max; i++ { - if !(moon[i] <= jieqi[j] && moon[i+1] > jieqi[j]) { + + // 确定闰月位置 + leapMonthPos := 20 + if moonCount == 13 { + solarTermIndex, i := 2, 0 + for i = minMoonIndex; i <= maxMoonIndex; i++ { + if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) { break } - j += 2 + solarTermIndex += 2 } - leapmonth = i - min + 1 + leapMonthPos = i - minMoonIndex + 1 } + + // 计算实际月份索引 + actualMonth := month if leap { - month++ + actualMonth++ } - if month > 10 { - month -= 11 + if actualMonth > 10 { + actualMonth -= 11 } else { - month++ + actualMonth++ } - if month >= leapmonth && !leap { - month++ + if actualMonth >= leapMonthPos && !leap { + actualMonth++ } - jde := moon[min-1+month] + float64(day) - 1 - return jde + + return newMoonDays[minMoonIndex-1+actualMonth] + float64(day) - 1 } -// Date2JDE 日期转儒略日 -func Date2JDE(date time.Time) float64 { - 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) +func normalizeTimeArray(timeArray []float64, tz float64) { + for idx, timeValue := range timeArray { + adjustedTime := timeValue + 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 } diff --git a/basic/calendar_test.go b/basic/calendar_test.go index df16372..fcf2f04 100644 --- a/basic/calendar_test.go +++ b/basic/calendar_test.go @@ -132,3 +132,88 @@ func magicNumberSpilt(magic int32) (uint16, uint8) { upper = uint16(magic >> 8) 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)) +} diff --git a/basic/moon.go b/basic/moon.go index 2bc1139..039d631 100644 --- a/basic/moon.go +++ b/basic/moon.go @@ -1430,162 +1430,202 @@ func MoonTimeAngle(JD, Lon, Lat, TZ float64) float64 { return timeangle } -func GetMoonRiseTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 { - ntz := TZ - TZ = Lon / 15 - var An, tms float64 = 0, 0 - JDZ := math.Floor(JD) + 0.5 - JD = math.Floor(JD) + 0.5 - ntz/24 + TZ/24.0 //求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) +func GetMoonRiseTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 { + originalTimeZone := timeZone + timeZone = longitude / 15 + var moonAngle, timeToMeridian float64 = 0, 0 + julianDayZero := math.Floor(julianDay) + 0.5 + julianDay = math.Floor(julianDay) + 0.5 - originalTimeZone/24 + timeZone/24 // 求0时JDE + estimatedTime := julianDay + moonHeight := MoonHeight(julianDay, longitude, latitude, timeZone) // 求此时月亮高度 + + if zenithShift != 0 { + moonAngle = -0.83333 // 修正大气折射 } - if moonheight < 0 && moonang > 180 { - tms = (180 - moonang) / 15 - JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) - } else if moonheight < 0 && moonang < 180 { - tms = (180 - moonang) / 15 - JD1 += (tms/24 + (tms/24*12.0)/15.0/24.0) - } - now := MoonTimeAngle(JD1, Lon, Lat, TZ) - if math.Abs(now-180) > 0.5 { - 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 //拱 + moonAngle = moonAngle - HeightDegreeByLat(height, latitude) + + moonAngleTime := MoonTimeAngle(julianDay, longitude, latitude, timeZone) + + if moonHeight > 0 { // 月亮在地平线上或在落下与下中天之间 + if moonAngleTime > 180 { + timeToMeridian = (180 + 360 - moonAngleTime) / 15 + } else { + timeToMeridian = (180 - moonAngleTime) / 15 } - reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0 - mag := MoonTimeAngle(reJde, Lon, Lat, TZ) - if mag < 90 { - mag += 360 + estimatedTime += (timeToMeridian/24 + (timeToMeridian/24*12.0)/15.0/24.0) + } + + 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 - if HMoonHeight(reJde, Lon, Lat, TZ) < An { - return -2 //沉 + checkTime := estimatedTime + 12.0/24.0 + 6.0/15.0/24.0 + checkAngle := MoonTimeAngle(checkTime, longitude, latitude, timeZone) + 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)) - if math.Abs(tmp) <= 1 && Lat < 85 { - SJ := (180 - ArcCos(tmp)) / 15 - JD1 += SJ/24.00 + SJ/33.00/15.00 + + moonDeclination := MoonApparentDec(estimatedTime, longitude, latitude, timeZone) + tmp := (Sin(moonAngle) - Sin(moonDeclination)*Sin(latitude)) / (Cos(moonDeclination) * Cos(latitude)) + + if math.Abs(tmp) <= 1 && latitude < 85 { + hourAngle := (180 - ArcCos(tmp)) / 15 + estimatedTime += hourAngle/24.00 + hourAngle/33.00/15.00 } else { i := 0 - for MoonHeight(JD1, Lon, Lat, TZ) < An { + for MoonHeight(estimatedTime, longitude, latitude, timeZone) < moonAngle { i++ - JD1 += 15.0 / 60.0 / 24.0 + estimatedTime += 15.0 / 60.0 / 24.0 if i > 48 { 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 { - return JD1 + return estimatedTime } } -func GetMoonDownTime(JD, Lon, Lat, TZ, ZS, HEI float64) float64 { - ntz := TZ - TZ = Lon / 15 - var An, tms float64 = 0, 0 - JDZ := math.Floor(JD) + 0.5 - JD = math.Floor(JD) + 0.5 - ntz/24 + TZ/24 //求0时JDE - JD1 := JD - moonheight := MoonHeight(JD, Lon, Lat, TZ) //求此时月亮高度 - if ZS != 0 { - An = -0.83333 //修正大气折射 +func GetMoonSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 { + originalTimeZone := timeZone + timeZone = longitude / 15 + var moonAngle, timeToMeridian float64 = 0, 0 + julianDayZero := math.Floor(julianDay) + 0.5 + julianDay = math.Floor(julianDay) + 0.5 - originalTimeZone/24 + timeZone/24 // 求0时JDE + + estimatedTime := julianDay + moonHeight := MoonHeight(julianDay, longitude, latitude, timeZone) // 求此时月亮高度 + + if zenithShift != 0 { + moonAngle = -0.83333 // 修正大气折射 } - An = An - HeightDegreeByLat(HEI, Lat) - moonang := MoonTimeAngle(JD, Lon, Lat, TZ) - if moonheight < 0 { - tms = (360 - moonang) / 15 - JD1 += (tms/24 + (tms/24.0*12.0)/15.0/24.0) + moonAngle = moonAngle - HeightDegreeByLat(height, latitude) + + moonAngleTime := MoonTimeAngle(julianDay, longitude, latitude, timeZone) + + 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 - JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0) - } else if moonheight > 0 { - tms = (360 - moonang) / 15 - JD1 += (tms/24.0 + (tms/24.0*12.0)/15.0/24.0) + + // 月亮在地平线上或在落下与下中天之间 + if moonHeight > 0 && moonAngleTime < 180 { + timeToMeridian = (-moonAngleTime) / 15 + estimatedTime += (timeToMeridian/24.0 + (timeToMeridian/24.0*12.0)/15.0/24.0) + } else if moonHeight > 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 { - now += 360 + + currentAngle := MoonTimeAngle(estimatedTime, longitude, latitude, timeZone) + if currentAngle < 180 { + currentAngle += 360 } - if math.Abs(now-360) > 0.5 { - JD1 += (360 - now) * 4.0 / 60.0 / 24.0 + if math.Abs(currentAngle-360) > 0.5 { + estimatedTime += (360 - currentAngle) * 4.0 / 60.0 / 24.0 } - //JD1=月球中天时间 - hei := HMoonHeight(JD1, Lon, Lat, TZ) - if !(hei > 10 && math.Abs(Lat) < 60) { - if hei < An { - return -2 //沉 + + // estimatedTime = 月球中天时间 + currentHeight := HMoonHeight(estimatedTime, longitude, latitude, timeZone) + if !(currentHeight > 10 && math.Abs(latitude) < 60) { + if currentHeight < moonAngle { + return -2 // 沉 } - reJde := JD1 + 12.0/24.0 + 6.0/15.0/24.0 - sub := 180 - MoonTimeAngle(reJde, Lon, Lat, TZ) - reJde += sub * 4.0 / 60.0 / 24.0 - if HMoonHeight(reJde, Lon, Lat, TZ) > An { - return -1 //拱 + checkTime := estimatedTime + 12.0/24.0 + 6.0/15.0/24.0 + angleSubtraction := 180 - MoonTimeAngle(checkTime, longitude, latitude, timeZone) + checkTime += angleSubtraction * 4.0 / 60.0 / 24.0 + if HMoonHeight(checkTime, longitude, latitude, timeZone) > moonAngle { + return -1 // 拱 } } - dec := MoonApparentDec(JD1, Lon, Lat, TZ) - tmp := (Sin(An) - Sin(dec)*Sin(Lat)) / (Cos(dec) * Cos(Lat)) - if math.Abs(tmp) <= 1 && Lat < 85 { - SJ := (ArcCos(tmp)) / 15.0 - JD1 += SJ/24 + SJ/33.0/15.0 + + moonDeclination := MoonApparentDec(estimatedTime, longitude, latitude, timeZone) + tmp := (Sin(moonAngle) - Sin(moonDeclination)*Sin(latitude)) / (Cos(moonDeclination) * Cos(latitude)) + + if math.Abs(tmp) <= 1 && latitude < 85 { + hourAngle := (ArcCos(tmp)) / 15.0 + estimatedTime += hourAngle/24 + hourAngle/33.0/15.0 } else { i := 0 - for MoonHeight(JD1, Lon, Lat, TZ) > An { + for MoonHeight(estimatedTime, longitude, latitude, timeZone) > moonAngle { i++ - JD1 += 15.0 / 60.0 / 24.0 + estimatedTime += 15.0 / 60.0 / 24.0 if i > 48 { 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 { - 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 { + previousTime := currentTime + + // 计算函数值:f(t) = height(t) - targetAngle + functionValue := heightFunc(previousTime, longitude, latitude, timeZone) - targetAngle + + // 计算导数: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 } } - JD1 = JD1 - TZ/24 + ntz/24 - if JD1 > JDZ+1 || JD1 < JDZ { - return -3 //明日 - } else { - return JD1 - } + + return currentTime } func GetMoonCir() [][][]float64 { diff --git a/basic/moon_test.go b/basic/moon_test.go index 18753e8..eb88b46 100644 --- a/basic/moon_test.go +++ b/basic/moon_test.go @@ -19,7 +19,7 @@ func Benchmark_MoonRiseBench(b *testing.B) { func Test_MoonDown(t *testing.T) { jde := GetNowJDE() 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) { @@ -100,5 +100,740 @@ func TestMoonCu(t *testing.T) { //ra, dec := HMoonApparentRaDec(jde, 115, 23, 8) //fmt.Println(tools.Format(ra/15, 1), tools.Format(dec, 0)) //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) + } } diff --git a/basic/sun.go b/basic/sun.go index 0623903..179342e 100644 --- a/basic/sun.go +++ b/basic/sun.go @@ -288,48 +288,66 @@ func GetJieqiLoops(year, loop int) []float64 { return jq } -func GetJQTime(Year, Angle int) float64 { //节气时间 - var j int = 1 - var Day int - var tp float64 - if Angle%2 == 0 { - Day = 18 +func GetJQTime(year, angle int) float64 { + // Calculate initial day based on angle parity + var initialDay float64 + if angle%2 == 0 { + initialDay = 18 } 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 { - tp = float64(Angle) / 30.0 + tempFactor = float64(angle) / 30.0 } - Month := 3 + tp - if Month > 12 { - Month -= 12 + + // Calculate initial month, adjusting if超过 12 + initialMonth := 3.0 + tempFactor + if initialMonth > 12.0 { + initialMonth -= 12.0 } - JD1 := JDECalc(int(Year), int(Month), float64(Day)) - if Angle == 0 { - Angle = 360 + + // Calculate initial Julian date + 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 { - JD0 := JD1 - stDegree := JQLospec(JD0) - float64(Angle) - stDegreep := (JQLospec(JD0+0.000005) - JQLospec(JD0-0.000005)) / 0.00001 - JD1 = JD0 - stDegree/stDegreep - if math.Abs(JD1-JD0) <= 0.00001 { - break - } + + // Newton-Raphson iteration to find precise Julian date + currentJD := initialJD + for { + previousJD := currentJD + errorValue := JQLospec(previousJD, targetAngle) - targetAngle + derivative := (JQLospec(previousJD+0.000005, targetAngle) - JQLospec(previousJD-0.000005, targetAngle)) / 0.00001 + 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) - if t <= 12 { - t += 360 + if target >= 345 { + if t <= 12 { + t += 360 + } + } else if target <= 15 { + if t >= 350 { + t -= 360 + } } return t } @@ -391,8 +409,8 @@ func GetWHTime(Year, Angle int) float64 { } for { JD0 := JD1 - stDegree := JQLospec(JD0) - float64(Angle) - stDegreep := (JQLospec(JD0+0.000005) - JQLospec(JD0-0.000005)) / 0.00001 + 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 @@ -503,96 +521,133 @@ func SunTimeAngle(JD, Lon, Lat, TZ float64) float64 { return timeangle } -/* - * 精确计算,传入当日0时JDE - */ -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 +// GetSunRiseTime 精确计算日出时间,传入当日0时JDE +func GetSunRiseTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 { + return calculateSunRiseSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height, true) } -func GetSunSetTime(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 + +// GetSunSetTime 精确计算日落时间,传入当日0时JDE +func GetSunSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height float64) float64 { + return calculateSunRiseSetTime(julianDay, longitude, latitude, timeZone, zenithShift, height, false) +} + +// 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) - tztime := GetSunTZTime(JD, Lon, ntz) - if SunHeight(tztime, Lon, Lat, ntz) < An { - return -2 //极夜 + sunAngle = sunAngle - HeightDegreeByLat(height, latitude) + + // 获取太阳上中天时间 + 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 - if math.Abs(tmp) <= 1 && Lat < 85 { - rzsc := ArcCos(tmp) / 15 - sundown = tztime + rzsc/24.0 + 35.0/24.0/60.0 - } else { - sundown = tztime - i := 0 - for LowSunHeight(sundown, Lon, Lat, ntz) > An { - i++ - sundown += 15.0 / 60.0 / 24.0 - if i > 48 { - break - } + + checkTime := solarNoonTime + 0.5 + if isSunrise { + checkTime = solarNoonTime - 0.5 + } + + if SunHeight(checkTime, longitude, latitude, naturalTimeZone) > sunAngle { + return -1 // 极昼 + } + + return 0 // 正常条件 +} + +// 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 { - 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 { + previousTime := currentTime + + // 计算函数值:f(t) = SunHeight(t) - targetAngle + functionValue := SunHeight(previousTime, longitude, latitude, naturalTimeZone) - sunAngle + + // 计算导数: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 } } - 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 { - tiangan := []string{"庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", "已"} + tiangan := []string{"庚", "辛", "壬", "癸", "甲", "乙", "丙", "丁", "戊", "己"} dizhi := []string{"申", "酉", "戌", "亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未"} t := year - (year / 10 * 10) + if t < 0 { + t += 10 + } d := year % 12 - return tiangan[t] + dizhi[d] + "年" + if d < 0 { + d += 12 + } + return tiangan[t] + dizhi[d] } diff --git a/calendar/astro.go b/calendar/astro.go index 6aa797e..0e9c40e 100644 --- a/calendar/astro.go +++ b/calendar/astro.go @@ -21,5 +21,3 @@ func Date2JDE(date time.Time) float64 { func JDE2Date(jde float64) time.Time { return basic.JDE2Date(jde) } - - diff --git a/calendar/chinese.go b/calendar/chinese.go index 7e96913..6e3ac2e 100644 --- a/calendar/chinese.go +++ b/calendar/chinese.go @@ -1,11 +1,19 @@ package calendar import ( + "fmt" + "math" + "regexp" + "strconv" + "strings" "time" "b612.me/astro/basic" ) +var tiangan = []string{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"} +var dizhi = []string{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"} + const ( JQ_春分 = 15 * iota JQ_清明 @@ -38,7 +46,7 @@ const ( // 返回 农历月,日,是否闰月以及文字描述 // 按现行农历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) } @@ -58,31 +66,96 @@ func Solar(year, month, day int, leap bool, timezone float64) time.Time { // SolarToLunar 公历转农历 // 传入 公历年月日 -// 返回 农历月,日,是否闰月以及文字描述 -// 忽略时区,日期一律按北京时间计算 -// 按现行农历GB/T 33661-2017算法计算,推荐使用年限为[1929-3000]年 -// 古代由于定朔定气误差此处计算会与古时不符 -func SolarToLunar(date time.Time) (int, int, bool, string) { - return basic.GetLunar(date.Year(), int(date.Month()), date.Day(), 8.0/24.0) +// 返回 包含农历信息的Time结构体 +// 支持年份:[-103,3000] +// [-103,1912] 按照古代历法提供的农历信息 +// (1912,3000]按现行农历GB/T 33661-2017算法计算 +func SolarToLunar(date time.Time) (Time, error) { + 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 农历转公历 -// 传入 农历年份,月,日,是否闰月 -// 传出 公历时间 -// 农历年份用公历年份代替,但是岁首需要使用农历岁首 -// 例:计算己亥猪年腊月三十日对应的公历(即2020年1月24日) -// 由于农历还未到鼠年,故应当传入Solar(2019,12,30,false) -// 按现行农历GB/T 33661-2017算法计算,推荐使用年限为[1929-3000]年 -// 古代由于定朔定气误差此处计算会与古时不符 -func LunarToSolar(year, month, day int, leap bool) time.Time { - jde := basic.GetSolar(year, month, day, leap, 8.0/24.0) - zone := time.FixedZone("CST", 8*3600) - return basic.JDE2DateByZone(jde, zone, true) +// 传入 农历描述,如"二零二零年正月初一","元丰六年十月十二","元嘉二十七年七月庚午日" +// 传出 包含公里农历信息的Time结构体切片 +// 传入参数支持如下结构 +// 农历年中文描述+农历月中文描述+农历日中文描述 +// 农历年中文描述+农历月中文描述+干支日中文描述 +// 年号+农历月中文描述+农历日中文描述 +// 年号+农历月中文描述+干支日中文描述 +// 支持年份:[-103,3000] +func LunarToSolar(desc string) ([]Time, error) { + dates, err := innerParseLunar(desc) + 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 返回传入年份对应的干支 -func GanZhi(year int) string { - return basic.GetGZ(year) +// LunarToSolarSingle 农历转公历 +// 传入 农历年月日,是否闰月 +// 传出 包含公里农历信息的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 返回传入年份、节气对应的北京时间节气时间 @@ -99,43 +172,11 @@ func WuHou(year, term int) time.Time { return basic.JDE2DateByZone(calcJde, zone, false) } -// RapidLunarToSolar 农历转公历(快速查表法) -// 传入 农历年份,月,日,是否闰月 -// 传出 公历时间 -// 农历年份用公历年份代替,但是岁首需要使用农历岁首 -// 例:计算己亥猪年腊月三十日对应的公历(即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) { +func rapidLunarModern(year, month, day int) (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 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 { - return 0, 0, false, "超过日期限制" + return 0, 0, 0, false, "超过日期限制" } useGoto := false recalc: @@ -144,7 +185,7 @@ recalc: springMonth := (magic&0x800000)>>23 + 1 springDay := (magic & 0x7FFFFF) >> 18 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))) { year-- @@ -187,7 +228,7 @@ recalc: } else { result += strday[lday/10] + strmonth[lday%10] } - return lunarMonth, lday, isLeap, result + return year, lunarMonth, lday, isLeap, result } totalDay += dayofLunar lunarMonth++ @@ -198,10 +239,10 @@ recalc: 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 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 { @@ -236,3 +277,241 @@ func rapidSolar(year, month, day int, isLeap bool) 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 +} diff --git a/calendar/chineseHantoQing.go b/calendar/chineseHantoQing.go new file mode 100644 index 0000000..817c8be --- /dev/null +++ b/calendar/chineseHantoQing.go @@ -0,0 +1,492 @@ +package calendar + +import ( + "errors" + "fmt" + "strings" + "time" +) + +var ERR_NIANHAO_NOT_FOUND = errors.New("ERROR:未找到对应的年号") + +func getHanQingCals() []uint32 { + return []uint32{ + 2865769984, 1431610368, 3310368000, 1788881408, 2874351360, 2865771008, 1431316224, 1789500416, 1520447232, 2866160640, 2862626304, 3578800896, 1521262848, 1436562432, 2863671296, 1431477760, 3041931264, 1436558848, 2863700480, 2862624000, 3042255360, 2907714816, 1432365568, 2863374080, 1788883456, 2907711232, 1432984576, 1431318272, 2863506432, 1520449280, 2865769216, 1432101120, 1431319552, 1520445696, 2874318080, 2863673344, 1431315968, 1520999168, 1453337856, 2863964672, 2862626048, 3578800640, 1454087936, 1432367616, 2862622464, 3578928128, 2907713024, 1437475840, 1431320320, 2862623744, 2907971584, 2874159872, 1431316736, 2863308288, 1788882944, 2874156288, 1431902976, 1431318016, 1789731328, 1453339904, 2865768960, 1431511040, 3578802432, 1453336320, 2865863680, 2862624512, 3579192064, 3041932800, 1436560384, 2863407360, 2862625536, 3041929216, 1437212160, 1432367360, 2862621952, 3041958400, 2874158336, 1433215744, 1431319808, 1788881408, 2907905792, 2865771008, 1431316224, 1789500416, 1520447232, 2866160640, 2863674880, 1431317504, 1521262848, 1436562432, 2863671296, 1431477760, 3041931264, 1453336064, 2863700480, 2862624000, 3042255360, 2907714816, 1432365568, 2863374080, 2862625280, 2907711232, 1432984576, 1431318272, 2863506432, 1520449280, 2874157824, 1432101120, 1431319552, 1520445696, 2874318080, 2863673344, 1431315968, 1789434624, 1453337856, 2863964672, 2862626048, 3578800640, 1454087936, 1436561920, 2862622464, 3578928128, 2907713024, 1437475840, 1431320320, 2862623744, 3042189312, 2874159872, 1431316736, 2863308288, 1788882944, 2874156288, 1432951552, 1431318016, 1789731328, 1453339904, 2865768960, 1431511040, 3578802432, 1520445184, 2865863680, 2862624512, 3579192064, 3041932800, 1436560384, 2863931648, 2862625536, 3041929216, 1437212160, 1432367360, 2862621952, 3041958400, 2907712768, 1433215744, 1431319808, 1788881408, 2907905792, 2865771008, 1431316224, 2863242240, 1520447232, 2866160640, 2863674880, 1431317504, 1521262848, 1453339648, 2863671296, 1431477760, 3041931264, 1453336064, 2863700480, 2862624000, 3579126272, 2907714816, 1432365568, 2863374080, 2862625280, 2907711232, 1437178880, 1431318272, 2863506432, 1520449280, 2874157824, 1432101120, 1431319552, 1788881152, 2874318080, 2863673344, 1431315968, 1788910336, 2862623744, 3042255104, 2874160128, 1432365568, 2863373824, 1788883200, 2907710976, 1432984576, 1431318016, 1789764352, 1520449024, 2865769216, 1432100864, 1431319296, 1520445440, 2865929472, 2863673088, 1431315712, 1520998912, 1453337856, 2863964416, 2862625792, 3041929472, 1454087936, 1432367360, 2862622208, 3578927872, 2907713024, 1433281280, 1431320064, 2862623488, 2907971584, 2874159616, 1431316480, 2863308032, 1520447488, 2874156032, 1431902720, 1431317760, 1789731328, 1453339648, 2863671552, 1431510784, 3578802432, 1453336064, 2865863424, 2862624256, 3579192064, 2907714816, 1436560128, 2863407104, 2862625536, 3041928960, 1437211904, 1431318528, 2862621952, 3041958144, 2874158080, 1433215488, 1431319808, 1788881152, 2874351104, 2865770752, 1431316224, 1789500160, 1453338112, 2866160384, 2862626304, 3578800640, 1521262592, 1436562176, 2862622720, 3578960896, 3041931008, 1436558592, 2863700480, 2862623744, 3042255104, 2874160128, 1432365568, 2863373824, 1788883200, 2907710976, 1432984576, 1431318016, 1789764352, 1520449024, 2865769216, 1432100864, 1431319296, 1520445440, 2865929472, 2863673088, 1431315712, 1520998912, 1453337856, 2863964416, 2862625792, 3041929472, 1454087936, 1432367360, 2862622208, 3578927872, 2907713024, 1433281280, 1431320064, 2862623488, 2907971584, 2874159616, 1431316480, 2863308032, 1520447488, 2874156032, 1431902720, 1431317760, 1789731328, 1453339648, 2863671552, 1431510784, 3578802432, 1453336064, 2865863424, 2862624256, 3579192064, 2907714816, 1436560128, 2863407104, 2862625536, 3041928960, 1437211904, 1431318528, 2862621952, 3041958144, 2874158080, 1433215488, 1431319808, 1788881152, 2874351104, 2865770752, 1431316224, 1789500160, 1453338112, 2866160384, 2862626304, 3578800640, 1521262592, 1436562176, 2862622720, 3578960896, 3041931008, 1436558592, 2863700480, 3041929984, 1454186752, 1432368128, 2862622976, 3042123008, 2907713536, 1432364544, 2863241984, 1788882176, 2908103168, 2865771776, 1431317248, 1789697792, 1453339136, 2865768192, 1431477504, 3578801664, 1453335552, 2865797376, 2862623744, 3579125760, 2907714304, 1436559616, 2863373824, 2862624768, 2907710720, 1437178624, 1431318016, 2863505920, 1520448768, 2874157568, 1432100864, 1431319040, 1520445184, 2874317824, 2863673088, 1431315456, 1520998656, 1453337600, 2863964416, 2862625536, 3578800128, 1454087680, 1432367360, 2862621952, 3042056704, 2907712768, 1433281280, 1431319808, 1788881408, 2907971328, 2865771008, 1431316224, 1789565952, 1520447232, 2865767424, 1431378176, 3578800896, 1521295616, 1436562432, 2862622720, 3578993920, 3041931264, 1436558848, 2863241728, 2862624000, 3042320896, 2874160384, 1431316992, 2863406848, 1788883456, 2874156800, 1431968768, 1431318272, 1788879872, 2874185984, 2862623488, 3042254848, 3578802944, 1453336832, 2863897856, 2862624768, 3578799360, 1453955840, 1432366336, 2863505920, 2862626048, 2907712000, 1433149184, 1431319040, 2862622464, 2907872256, 2865769984, 1431315456, 2863175936, 1520446464, 2866094080, 2863674112, 1431316736, 1521196544, 1436561408, 2863670528, 1431444224, 3041930496, 1437475328, 1432368384, 2862623232, 3042189056, 2874159360, 1432364800, 2863307776, 1788882688, 2874155776, 1432951040, 1431317504, 1789731072, 1453339392, 2865768448, 1431510528, 3578802176, 1453335808, 2865863168, 2862624000, 3579191808, 2907714560, 1436559872, 2863406848, 2862625280, 2907710976, 1437211648, 1431318272, 2862621696, 2907740160, 2865769216, 1432166656, 1431319552, 1520445440, 2865995008, 2863673344, 1431315968, 1521064448, 1436560640, 2864062976, 2862626048, 3041929472, 1437376256, 1432367616, 2862622464, 3042089728, 2874158592, 1432364032, 2863175936, 1788881664, 2874482688, 2865771264, 1431316736, 1789631744, 1453338624, 2865767680, 1431411456, 3578801152, 1454219776, 1436562688, 2862623232, 3579059712, 2907713792, 1436559104, 2863307776, 2862624256, 2907710208, 1437145344, 1431317504, 2863472640, 1520448256, 2874157056, 1432034816, 1431318528, 1520444672, 2874251776, 2863672576, 1431708160, 3041932288, 1453337088, 2863931136, 2862625024, 3041928704, 1453988864, 1432366848, 2862621440, 3041957888, 2907712256, 1433215232, 1431319296, 2862622720, 2907905280, 2865770496, 1431315712, 1789499904, 1520446720, 2866160128, 2862625792, 3578800384, 1521262336, 1436561920, 2862622208, 3578960640, 3041930752, 1436558336, 2863306752, 2862623488, 3041927168, 1437144576, 1431316480, 2863471872, 1788882944, 2874156288, 1432033792, 1431317760, 1788879360, 2874251008, 2863671552, 1431707392, 3041931520, 1453336320, 2863962880, 2862624256, 3041927936, 1454020864, 1432365824, 2862620672, 3041957120, 2907711488, 1433246976, 1431318528, 1788880128, 2907937280, 2865769472, 1431314944, 1789499136, 1520445952, 2866159104, 2862625024, 3578799616, 1521261568, 1436560896, 2862621440, 3578959872, 3041929984, 1436557312, 2863174912, 2862622720, 3042254080, 2874158848, 1431315712, 2863372800, 1788882176, 2874155264, 1431967488, 1431316992, 1789796096, 1453338880, 2863670784, 1431575552, 3578801664, 1453335296, 2863831040, 2862623488, 3578798080, 1453921536, 1432365056, 2863471872, 2862624768, 2907710464, 1433082368, 1431317760, 2862621184, 2907805184, 2865768704, 1431707392, 3578802432, 1520444928, 2866027264, 2862624256, 3578798848, 1521129472, 1436560128, 2862620672, 3578860800, 3041928960, 1437408512, 1431318528, 2862621952, 3042121984, 2874158080, 1431314944, 2863240960, 1788881152, 2874547712, 2863673600, 1431316224, 1789696768, 1453338112, 2863670016, 1431476480, 3578800640, 1453334528, 2863699200, 2862622720, 3579124736, 2907713280, 1432364288, 2863372800, 2862623744, 2907709696, 1432983296, 1431316992, 2863504896, 1520447744, 2865767936, 1432099840, 1431318016, 1520444160, 2865928192, 2863672064, 1431314432, 1521030400, 1436559360, 2863996160, 2862624512, 3041928192, 1437276672, 1432366336, 2862620928, 3042055680, 2874157312, 1433280256, 1431318784, 1788880384, 2874415872, 2865769984, 1431315200, 1789564928, 1453337344, 2865766400, 1431377152, 3578799872, 1454218496, 1436561408, 2862621696, 3579025664, 2907712512, 1436557824, 2863240704, 2865768704, 1431707392, 3578802432, 1520444928, 2866092800, 2862624256, 3578798848, 1433049088, 1431317248, 1788878848, 2874184960, 2865768192, 1431641344, 3578801920, 1453335808, 2865993984, 2862623744, 3578798336, 1453954816, 1436559616, 2863504896, 2862625024, 2907710976, 1437375232, 1431318016, 2862621440, 2907871232, 2874157568, 1431314432, 3312522496, 2773493760, 3534560256, 2996842240, 3578799104, 1454086656, 1436560384, 2781880576, 1255773952, 1236281856, 2833128960, 2773496064, 2862622208, 3042188032, 2907712768, 1302340352, 2782009344, 2775591680, 1387274240, 2763592960, 1689266176, 1789730048, 1520447232, 2874156032, 1265834496, 1256205568, 1453334784, 2863764992, 2862622976, 3042319872, 2907713536, 1432364544, 2863438592, 1788882432, 2907709952, 1433049088, 1431317248, 1788878848, 2907739136, 2865768192, 1431641344, 3578801920, 1520444416, 2865993984, 2862623744, 3578798336, 1521063424, 2840602880, 3031309824, 1788883200, 2875204864, 1437899520, 1265643008, 1164977152, 1387960320, 1387277056, 1766858752, 1789498624, 1520445184, 2874514432, 2530225920, 1256203520, 2775816448, 2765106176, 3530563840, 1498584832, 3041929216, 1453334016, 2865795840, 2513446400, 1257020160, 1236282880, 2765103872, 3530201088, 2862623232, 3041926912, 1453921536, 765470720, 2514820096, 2507157248, 1236280576, 2763758080, 1689267200, 1787830528, 2907837952, 1800415488, 727719424, 2511377152, 2473600512, 1237097472, 1248865792, 1766859520, 1788549120, 1520446208, 1792024320, 1265177856, 1256204288, 2775981312, 2463117056, 3396346880, 1420532224, 3030395904, 3113230336, 1532139008, 2530224384, 653139712, 1238380800, 2731550208, 2993462016, 1766862336, 2862621184, 2907903744, 2875206144, 1437605888, 1236899072, 628107264, 1387633920, 3533713152, 3931120384, 1831606528, 1520446464, 2874155264, 2511476224, 2472552704, 3379568128, 1689326592, 3567265024, 3931445760, 3578801408, 1520444160, 2865960704, 2799708672, 2464161792, 2775160064, 2773493504, 3534593024, 1788882688, 3041928192, 1454119168, 1439706112, 634397184, 2463766272, 1389373696, 2840600064, 3030946560, 2862622208, 3042253312, 2874158336, 1268785920, 2779977728, 2742036992, 1383079936, 1689883904, 1429219328, 1789238272, 3667930624, 2605720576, 728504832, 1256205312, 2774540544, 3518666240, 1231038976, 3568311552, 1519424256, 3600819456, 1456806656, 1439706368, 634397440, 2733283328, 2463116032, 2840600320, 3567916032, 2904565504, 3047562240, 2879401472, 1437606912, 1237064192, 1164979456, 1387274496, 2841286144, 1766861056, 1788878336, 2907738624, 2875204864, 1265965824, 1256205824, 2775589376, 1387468800, 3533711872, 3931119360, 1789498368, 1522542336, 2876120064, 383791104, 2329945088, 3312720128, 2841652224, 3567264000, 3646067968, 3041929216, 1453334016, 2865795840, 2781881600, 2463963904, 1387277824, 2832212736, 3568015104, 2996840960, 3041926912, 1453954304, 1302341376, 2780175360, 2775592704, 1387275520, 2830866688, 1697655808, 1788879104, 2874316288, 2874157056, 1264590336, 2775618304, 2775590400, 1366596352, 3511692544, 3576701440, 1788581888, 1453337088, 1523588864, 1265210624, 1256204288, 2733480960, 2731552512, 3511690240, 3568015616, 3038784256, 3047170048, 1456608768, 1437608192, 1238375936, 2765689600, 2729453056, 2858228480, 1783639296, 2904564224, 3043170048, 2875206144, 1437605632, 1169790208, 1164978176, 1656102144, 3568315904, 1783636992, 1789663488, 1520446464, 2875203584, 1399461376, 2464164096, 3311410688, 3567849984, 3567265024, 3646233088, 3041930496, 1453335040, 2865993472, 2781882880, 1389371392, 2841220096, 2840602368, 3534593024, 2862624512, 3041927936, 1437374720, 1268788224, 2511347968, 1387959808, 1236281600, 2830114304, 2996343552, 1788880128, 2908035584, 1800416512, 727720704, 2775783168, 2742036992, 1366302720, 1756501248, 3576702464, 1519787008, 3600821760, 1456481280, 720115968, 1256205312, 2732597504, 3513423360, 3377473536, 3575651584, 3666940416, 3047171328, 1456806400, 1437609216, 1171268352, 2732267520, 2729454080, 2840600320, 3031045120, 1830823680, 2909149952, 2875207168, 1437606912, 1169955328, 1164979200, 1387274496, 1767020032, 3914344448, 1788878080, 2907738624, 2875204864, 1399167744, 3401591808, 3848282368, 3534460672, 3533711872, 3645906432, 1521062912, 1453336320, 2799049728, 2513448448, 1255154688, 2765854976, 2765106176, 2992644096, 3042088192, 3041929216, 1436556800, 2513474048, 2511348992, 1253874432, 1236282880, 2763006464, 2862323456, 1788881408, 2907709184, 1302959104, 727721728, 2507545600, 2742038272, 1366303744, 1689524480, 3568315136, 1519395072, 1800574208, 1456482304, 719330816, 2473661184, 2732598528, 3379370496, 2840603904, 3567264256, 3667105280, 3047172352, 1456480000, 718902528, 634398464, 2464029696, 2461019904, 2840601600, 3031209984, 2896177920, 2907709440, 1437767168, 1269835776, 632299008, 2461602560, 1387275776, 1767709184, 1498426624, 1788879360, 2874382080, 2875205888, 1264590592, 2775684096, 2775590656, 1387666432, 3533712896, 3578798848, 1521260800, 1453337344, 2530222080, 1256887808, 1255155968, 2765102336, 3530101248, 2992645376, 3042253312, 2907712512, 899686912, 2513639168, 2511350272, 1236279040, 2765755392, 2763007744, 2858294272, 1788882432, 1833968384, 766286080, 726674432, 2473598976, 1232246272, 3379570688, 1689263616, 1783697920, 3666879488, 1800739328, 1456483584, 652222976, 2473793280, 2464164352, 3378519808, 3567915776, 3567265280, 3600161536, 2912955904, 1456481024, 651991296, 634399744, 2461016320, 2841285888, 2840602624, 3030392064, 3041956352, 2908759040, 1437964800, 1269837056, 632300288, 1388025600, 1387276800, 1766858496, 1789498368, 1788880384, 2874546944, 2808098304, 1264591872, 2775848960, 2774543104, 3529515008, 3912406272, 3578799872, 1520442624, 2874249728, 2530223360, 1257085440, 1238379776, 2765103616, 3530266368, 2857380096, 3041926656, 1453986816, 899688192, 2513443584, 1255706880, 1236280320, 2763823360, 1689266944, 2857377792, 3041596672, 1800415232, 765467904, 2511409664, 2473600256, 1232476928, 3379571712, 1689264640, 1783895808, 3662686464, 1530928640, 2875855616, 719333120, 2464160768, 3379630080, 3378520832, 3568080896, 3567266560, 3595575040, 1521161472, 1439705088, 651173376, 2464748032, 2461017344, 2841451008, 2840603904, 3030393088, 3042186752, 2907711744, 1437605632, 632951808, 628107008, 1387273216, 2841153792, 1766859520, 1789696000, 1520446208, 2874155008, 1265276160, 1264592896, 2775588096, 1383174912, 3529516032, 3912603904, 3578801152, 1520443904, 2605979136, 2530224384, 1256201984, 2766803968, 2765104640, 3528465152, 3643346944, 3040879360, 3601667840, 765471488, 2513444864, 1255872000, 1236281344, 2763005184, 2992247296, 1783637248, 3039664384, 1799367680, 2875203840, 2511607552, 2473601280, 1232084736, 1689916416, 1420830464, 1784027904, 3662687488, 1522541312, 2876053504, 652225280, 2464161792, 3379762432, 3378522112, 3567262720, 3662745856, 3578799104, 1454217728, 1437608960, 634397184, 2464913152, 2456824320, 2840600064, 3567948544, 3030394368, 3041925888, 1453887488, 1303388928, 632592640, 2775591680, 1387274240, 2841318656, 1766860800, 1788878080, 2907803904, 2874156032, 1265474048, 1256205568, 2775589120, 1383307008, 3529517312, 3912244736, 1789563648, 1520444928, 2605718272, 1265176832, 1256203008, 2767001600, 2765105920, 3529515008, 3576370176, 3038783232, 3600817152, 1456542208, 2513445888, 1239292416, 1236282624, 2763006464, 2858161664, 1783638272, 3040878080, 3047297792, 2875204864, 2511346432, 1236865280, 1232086016, 1690081280, 1420831488, 1783635968, 1831572736, 1522542336, 2875202560, 2473693696, 2464163072, 3379960064, 3378523136, 3567264000, 3662943744, 3041929216, 1453334016, 2866451200, 634398464, 2464160512, 3378057216, 2840601344, 3568080896, 2996840960, 3041926912, 1454085376, 1302341632, 2779782144, 1387926016, 1387275520, 2839419392, 1764764672, 1788879104, 2907969024, 2874157312, 1264590336, 2775716608, 2775590400, 1383078912, 1764823040, 3845136896, 1822234624, 1453337344, 1531977472, 1265308928, 1256204288, 2766150912, 3530166528, 3529516032, 3576535296, 3038784512, 3063947264, 1456772608, 1433413888, 1238376192, 2765787904, 2763007488, 2857376512, 3039334400, 3038781952, 3046446848, 2875206144, 2511347712, 1236997376, 1232087040, 1689263360, 2857996800, 1783636992, 1798150400, 1522543616, 2875203840, 720115200, 1239427328, 2765102592, 3529151232, 2991596800, 3038779904, 3666939648, 3047170560, 2513770240, 2511350272, 1236279296, 2763724032, 2763007744, 2857376768, 3039432960, 1832920064, 2909149184, 2875206400, 2473599232, 1239160576, 1232087296, 1689263616, 1783796480, 3662685440, 1520441856, 2875232000, 2799706624, 2465044480, 2464164352, 3378519808, 3568014336, 3567265536, 3578796800, 1521062144, 1453335552, 2798655744, 2464714240, 2461016320, 2774275584, 2840602880, 2996837632, 3042087424, 2907710720, 1302338304, 2781908736, 2775589376, 1388091392, 1383082752, 1764761344, 1788580864, 1788880640, 2874153984, 1269403904, 1264591872, 2792757504, 2732600320, 3512737792, 3912504576, 3567265792, 3667926272, 1532137984, 1456481536, 1256200960, 2733182976, 2731549184, 3512538880, 2857380352, 3038781184, 3601044224, 2912953856, 1439702016, 1238995456, 1169171456, 2729449728, 3512241664, 2857378048, 3039597824, 1797269504, 2908757248, 1437766400, 2473600256, 1164974848, 2730070016, 1387275008, 1783961344, 3645909248, 1520443136, 2875429888, 2799707648, 1390418944, 3312554240, 2774541312, 3534592000, 3533712128, 3578798080, 1521260032, 1453336576, 2798656768, 1391104768, 1387275776, 2832210432, 3534294784, 2996838912, 3042252544, 2907711744, 1302339328, 2782073856, 2775590656, 1370496000, 2830766336, 1697653760, 1788745984, 1520446208, 2874155008, 732730880, 727722240, 2742033664, 1366463232, 3512739072, 3836746240, 1787924224, 3667927296, 1532335872, 1456482816, 719331072, 2733347840, 2731550464, 3511688192, 3567915008, 3038782208, 3063289856, 2912955136, 1439703040, 635213312, 1169172736, 2729451008, 2841285120, 2840601856, 3038779904, 3041955584, 2875203840, 1437996800, 1265641984, 1164976128, 1388024832, 1387276032, 1766857728, 1823084800, 1520444160, 2874546176, 2799708928, 1256202496, 2775848192, 2774542336, 3533708544, 3914535424, 3578799104, 1453332992, 2865827584, 2513445376, 1257084672, 1236281856, 2765102848, 3530265600, 2996839936, 3041925888, 1453986048, 765469696, 2511345664, 1253608960, 1236279552, 2763822592, 1689266176, 1787829504, 2907902464, 1800414464, 727718400, 2507214592, 2473599488, 1232443392, 3378522368, 3836747264, 1788056576, 3667928576, 1523587840, 728338688, 652223488, 2464160000, 3379105024, 3377471488, 3568080128, 3030394880, 3062897664, 1456673280, 1437607168, 634395392, 2463698688, 2461016576, 2841450240, 1766861312, 1956650496, 3042185984, 2875205120, 1404050432, 632951040, 628106240, 1387272448, 2841153024, 1766858752, 1789695232, 1520445440, 2874154240, 1265275392, 1256203520, 2742032896, 1383174144, 3533709568, 3646264832, 3041929472, 1453334272, 2530448128, 2513446400, 1256201216, 2765754624, 2765103872, 3528464384, 3578825984, 3041927168, 1454150912, 765470720, 2511346944, 1236964096, 1232086272, 2763004416, 2992246528, 1787830784, 2908100096, 1531980032, 727719680, 2507412480, 2465211904, 1232083968, 1689391360, 3567264512, 3931510528, 3599772160, 1456480256, 728569344, 652224512, 2464161024, 3379237376, 3377472768, 3567261952, 3662745088, 3046121728, 1456871168, 1437608192, 634396416, 2463863808, 2461017856, 2840599296, 3031076864, 1822434048, 2907707392, 1437633792, 1269833728, 633116160, 628107520, 1387273472, 2840793600, 3914343424, 1788877312, 2907803136, 2874155264, 1265473280, 1256204800, 2775588352, 1382781952, 3529516544, 3645905664, 1521127424, 1453335296, 2530220032, 1256787456, 1256202240, 2765952256, 2765105152, 3528465664, 3578466560, 3041928192, 899684864, 2513506048, 2511347968, 1237194496, 1232087552, 2763005696, 2992378624, 1783637504, 1832917760, 2913603584, 727720704, 2473596928, 1232672768, 1232087808, 1689558784, 3567268096, 3931121152, 1800084480, 1456483840, 727720960, 2465306880, 2464164864, 3379404800, 2840605440, 3567265792, 3662945536, 3041931008, 1454384384, 651827968, 634400256, 2463113728, 3378059008, 2840603136, 3031211776, 1788883200, 2907710976, 1437277184, 1269837568, 632300544, 1387895040, 1387277312, 2840961280, 3914347008, 1788880896, 2907970816, 2605723648, 1264592128, 2775718400, 2767203584, 1382032128, 3912308224, 3578800384, 1521295104, 1453339136, 2530223616, 1256922112, 1239428864, 2765104128, 3530168320, 3528469248, 3576537088, 3040883456, 3047171840, 2513706240, 2511351808, 1236280832, 2763659776, 2763009280, 2857378304, 3039336192, 1832921344, 2913836544, 727724544, 2473600768, 1232804864, 1232088832, 1689265152, 1783765248, 3662686720, 1797267456, 2875266304, 2875205632, 2473270528, 2464165888, 3378521344, 3567950336, 3567266816, 3662684416, 1521063680, 1453337088, 2798886400, 2781884672, 2463115008, 2841320448, 2840604160, 3030393600, 3042056192, 2907712256, 1436557312, 2781943040, 2779785216, 1388027392, 1387278336, 1764762880, 1957337600, 1788882176, 2907709696, 1302959872, 1264593408, 2775850752, 2766156032, 3529516544, 3912440576, 3575655936, 3667927552, 1800542208, 1456483072, 1256202496, 2766771456, 2765105152, 3529219328, 2991599616, 3575653376, 3600980224, 3047173120, 1439703552, 1255773952, 1236281856, 2763759360, 2763010560, 2857379584, 3039501312, 1830825728, 2912953344, 1437735168, 2473602048, 1232085504, 1689884416, 1689266432, 1783864832, 3662688256, 1520444928, 2875365888, 2866818304, 2464162560, 3379664896, 3378522624, 3568049920, 3567268352, 3578799872, 1521163264, 1453338368, 2798658560, 1391073792, 1389374464, 2840600832, 3567883776, 3030395136, 3042155776, 2907713536, 1436558848, 2782042880, 2779786496, 1387275008, 2830768128, 1764764416, 1788649216, 1788883456, 2874156800, 1303059712, 1264594688, 2775589888, 1366432256, 3512740864, 3912245248, 1787926016, 3667929088, 1532206592, 1456484352, 1256203776, 2766838528, 2731552256, 3511689728, 3576305408, 3038784000, 3600064256, 2912956672, 1439704832, 719002880, 1169174528, 2729452544, 2975504640, 2840603648, 3038781696, 3046184192, 2908760064, 1437834752, 1399861504, 1164977664, 1656396544, 1387277824, 1766859520, 1823053568, 1520445952, 2874482432, 2798662144, 1256204032, 2775784448, 2774544128, 3533710336, 3914504192, 3578800896, 1520443648, 2874250752, 2798659584, 1256955392, 1253060864, 2832213504, 3534395904, 2996841728, 3041927680, 1453987840, 1302342144, 2513444608, 1253643520, 1236281344, 2830834688, 1689267968, 1787831296, 3042056448, 1800416256, 731914752, 2511410944, 2473601536, 1366499072, 3512742144, 3836749312, 1787993088, 3666881792, 1531978496, 728340736, 719334400, 2732597248, 3513324800, 3377473536, 3567983872, 3038785280, 3062899712, 1456609792, 1439706368, 634397184, 2732168960, 2729454080, 2841353984, 2840604928, 3030394368, 3042089728, 2907713024, 1437606656, 632953088, 628108288, 1388093696, 1387279104, 1766860800, 1823153408, 1520447488, 2874156032, 1399462400, 1256205568, 2775589376, 1386845952, 3533711616, 3914571264, 3578802432, 1520444928, 2865928960, 2513448448, 1256203264, 2774145024, 2765105920, 3529252864, 2995794688, 3041928960, 1454087424, 765472768, 2513446144, 1253743104, 1236282624, 2763006464, 2992215808, 1787832576, 2907446784, 1800417536, 727721728, 2511510272, 2473602560, 1232086016, 1689393408, 3835701760, 3931447040, 3666883072, 1523591168, 728440064, 719335424, 2464163072, 3379206656, 3377474560, 3567264000, 3662779904, 3062900992, 1456709120, 1437610240, 634398464, 2463800320, 2461019648, 2840601344, 3567917056, 3030395648, 3041926912, 1453921536, 1437607936, 633019904, 628109312, 1387275520, 2840762880, 3914345472, 1788879104, 2907805184, 2874157312, 1265377024, 1256206848, 2775590656, 1382718720, 3529518848, 3645907712, 1789532416, 1453337600, 2597331200, 1256789504, 1256204544, 2765823488, 2765107456, + } +} + +// 处理公元-105-1912年间的农历 +// 返回:农历年,农历月,农历月干支(闰月从上月),农历日,是否闰月,农历日期字符串 +func rapidLunarHan2Qing(year, month, day int, diff int, options func() map[int]uint32) (int, int, string, int, bool, string) { + useGoto := false + beijingTime := time.FixedZone("CST", 8*3600) +recalc: + idx := year + 105 + magic := getHanQingCals()[idx] + if options != nil { + if v, ok := options()[year]; ok { + magic = v + } + } + springDays := int8((magic >> 7)) >> 1 + if springDays>>6 == 1 { + springDays = -(springDays << 2 >> 2) + } + springDate := time.Date(year-1, 12, 31, 0, 0, 0, 0, beijingTime).AddDate(0, 0, int(springDays)) + if !useGoto && (int(springDate.Month()) > month || ((int(springDate.Month()) == month) && springDate.Day() > day)) { + year-- + useGoto = true + goto recalc + } + calcYear := year + if useGoto { + calcYear++ + } + target := time.Date(calcYear, time.Month(month), day, 0, 0, 0, 0, time.Local) + diffDay := int(target.Sub(springDate).Hours() / 24) + //go语言在; 1582年10月4日前,使用的是逆推格里高利历,与实际使用的儒略历有所不同,主要体现在百年闰年计算上! + //儒略历修正 + if springDate.Year()%100 == 0 && springDate.Year()%400 != 0 && springDate.Year() < 1582 && (target.Month() >= 3 || (target.Year() > springDate.Year())) { + diffDay++ + } + //儒略历转格里高历修正 + if calcYear == 1582 && ((month == 10 && day >= 15) || month > 10) { + diffDay -= 10 + } + if calcYear == 1583 && month == 1 && day <= 23 { + diffDay -= 10 + } + lunarMonth := 1 + totalDay := 0 + isLeap := false + leapMonth := int(uint8(magic>>15) & 0xF) + for i := 0; i < 13; i++ { + var dayofLunar = 29 + if uint8(magic>>(31-i))&1 == 1 { + dayofLunar++ + } + if totalDay+dayofLunar > diffDay { + lday := diffDay - totalDay + 1 + + format := formatLunarDateString(lunarMonth, lday, isLeap, diff) + ganzhiOfMonth := commonGanZhiOfMonth(year, lunarMonth) + + if diff == 255 { + diff = 2 + } + if diff != 0 { + lunarMonth += diff + if lunarMonth > 12 { + lunarMonth -= 12 + year++ + } + } + return year, lunarMonth, ganzhiOfMonth, lday, isLeap, format + } + totalDay += dayofLunar + lunarMonth++ + if lunarMonth-leapMonth == 1 && !isLeap { + isLeap = true + lunarMonth-- + } else { + isLeap = false + } + } + return 0, 0, "", 0, false, "无法获取农历信息" +} + +func rapidSolarHan2Qing(year, month, day int, isLeap bool, diff int, options func() map[int]uint32) time.Time { + useGoto := false + beijingTime := time.FixedZone("CST", 8*3600) +recalc: + idx := year + 105 + magic := getHanQingCals()[idx] + if options != nil { + if v, ok := options()[year]; ok { + magic = v + } + } + springDays := int8((magic >> 7)) >> 1 + if springDays>>6 == 1 { + springDays = -(springDays << 2 >> 2) + } + springDate := time.Date(year-1, 12, 31, 0, 0, 0, 0, beijingTime).AddDate(0, 0, int(springDays)) + if diff == 255 { + diff = 2 + } + if diff > 0 && !useGoto { + month = month - diff + if month <= 0 { + month += 12 + year-- + useGoto = true + goto recalc + } + } + + lunarMonth := 1 + totalDay := 0 + leap := false + leapMonth := int(uint8(magic>>15) & 0xF) + for i := 0; i < 13; i++ { + if lunarMonth == month && isLeap == leap { + target := springDate.AddDate(0, 0, totalDay+day-1) + if target.Year() == 1582 && ((target.Month() == 10 && target.Day() > 4) || target.Month() > 10) { + target = target.AddDate(0, 0, 10) + } + //go语言在; 1582年10月4日前,使用的是逆推格里高利历,与实际使用的儒略历有所不同,主要体现在百年闰年计算上! + //儒略历修正 + if springDate.Year()%100 == 0 && springDate.Year()%400 != 0 && springDate.Year() < 1582 && (target.Month() >= 3 || (target.Year() > springDate.Year())) { + target = target.AddDate(0, 0, -1) + } + return target + } + var dayofLunar = 29 + if uint8(magic>>(31-i))&1 == 1 { + dayofLunar++ + } + totalDay += dayofLunar + lunarMonth++ + if lunarMonth-leapMonth == 1 && !leap { + leap = true + lunarMonth-- + } else { + leap = false + } + } + return time.Time{} +} + +func yearDiff(year, month, day int) int { + // 王莽改制,公元9年-22年,建丑为正月 + // 注意,公元23年恢复建寅为正月,但是当年还是新朝地皇四年,如果在新朝的角度,当年还是建丑为正月! + if year == 9 && month == 1 && day < 15 { + return 0 + } + if year == 23 && month == 12 && day == 31 { + return 0 + } + if year >= 9 && year <= 23 { + return 1 + } + //魏明帝改制,公元237年-240年,建丑为正月 + if year == 237 && month > 4 { + return 1 + } + if year == 237 && month == 4 && day >= 12 { + return 1 + } + if year > 237 && year < 240 { + return 1 + } + if year == 240 && month == 1 && day < 12 { + return 1 + } + //武则天改制,公元690年-700年,建子为正月 + if year == 689 && month == 12 && day >= 18 { + return 255 + } + if year >= 690 && year < 700 { + return 255 + } + if year == 700 && (month < 12 || month == 12 && day <= 14) { + return 255 + } + //唐肃宗改制,公元761-762年,建寅为正月 + if year == 761 && month == 12 && day >= 2 { + return 2 + } + if year == 762 && month < 4 { + return 2 + } + if year == 762 && month == 4 && day < 29 { + return 2 + } + return 0 +} + +func yearDiffLunar(year, month, day int) int { + // 王莽改制,公元9年-22年,建丑为正月 + // 注意,公元23年恢复建寅为正月,但是当年还是新朝地皇四年,如果在新朝的角度,当年还是建丑为正月! + if year >= 9 && year <= 23 { + return 1 + } + //魏明帝改制,公元237年-240年,建丑为正月 + if year == 237 && month >= 4 { + return 1 + } + if year > 237 && year < 240 { + return 1 + } + + //武则天改制,公元690年-700年,建子为正月 + if year >= 690 && year < 700 { + return 255 + } + //有两个12月 + if year == 700 && month != 11 { + return 255 + } + //唐肃宗改制,公元761-762年,建寅为正月 + if year == 762 && month <= 5 { + return 2 + } + return 0 +} + +func formatLunarDateString(lunarMonth, lunarDay int, isLeap bool, diff int) string { + monthNames := []string{"十", "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊"} + dayNames := []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"} + dayPrefixes := []string{"初", "十", "廿", "三"} + switch diff { + case 1: + monthNames = []string{"十", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊", "正"} + case 2: + monthNames = []string{"十", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊", "正", "二"} + case 3: + monthNames = []string{"十", "四", "五", "六", "七", "八", "九", "十", "冬", "腊", "正", "二", "三"} + case 255: + //武则天改制,将冬月成为正月,正月改为一月 + monthNames = []string{"十", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "正", "腊"} + } + var dateString string + + if isLeap { + dateString += "闰" + } + dateString += monthNames[lunarMonth] + "月" + + if lunarDay == 20 { + dateString += "二十" + } else if lunarDay == 10 { + dateString += "初十" + } else { + dateString += dayPrefixes[lunarDay/10] + dayNames[lunarDay%10] + } + + return dateString +} + +func innerSolarToLunarHanQing(date time.Time) Time { + year := date.Year() + month := int(date.Month()) + day := date.Day() + yeardiff := yearDiff(year, month, day) + lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, yeardiff, nil) + var eras []EraDesc + if lyear >= -103 && lyear <= 220 { + eras = innerEras(lyear, hanEras) + } else if lyear >= 221 && lyear <= 617 { + eras = innerEras(lyear, weiJinNanBeiChaoEras) + } else if lyear >= 618 && lyear <= 907 { + eras = innerEras(lyear, tangEras) + } else if lyear > 907 && lyear < 1368 { + eras = innerEras(lyear, wudaiSongYuanEras) + } else if lyear <= 1912 { + eras = innerEras(lyear, mingQingEras) + } + ldate := LunarTime{ + solarDate: date, + year: lyear, + month: lmonth, + day: lday, + leap: isLeap, + desc: ldesc, + eras: eras, + ganzhiMonth: ganzhiMonth, + comment: "", + } + var otherLunars []LunarTime + //王莽特殊处理 + if lyear == 23 { + liuxiu := ldate.eras[len(ldate.eras)-1:] + ldate.eras = ldate.eras[:1] + if month > 2 || (month == 2 && day >= 10) { + lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc = rapidLunarHan2Qing(year, month, day, 0, nil) + otherLunars = append(otherLunars, LunarTime{ + solarDate: date, + year: lyear, + month: lmonth, + day: lday, + leap: isLeap, + desc: ldesc, + eras: liuxiu, + ganzhiMonth: ganzhiMonth, + comment: "", + }) + } + } + + result := Time{ + solarTime: date, + lunars: append([]LunarTime{ldate}, otherLunars...), + } + //三国时期 + if year >= 220 && year <= 280 { + return innerSolarToLunarSanGuo(result) + } + //南北朝时期 + if year >= 384 && year <= 589 { + return innerSolarToLunarNanBeiChao(result) + } + //五代十国辽金元 + if year >= 947 && year <= 1279 { + return innerSolarToLunarLiaoJinYuan(result) + } + if year > 1644 && year < 1884 { + return innerSolarToLunarNanMing(result) + } + return result +} + +func innerParseLunar(lunar string) ([]time.Time, error) { + date, err := parseChineseDate(lunar) + if err != nil { + return []time.Time{}, err + } + if date.year != 0 && date.comment == "" { + if date.year < -103 || date.year > 3000 { + return nil, fmt.Errorf("年份超出范围") + } + if date.year <= 1912 { + d := rapidSolarHan2Qing(date.year, date.month, date.day, date.leap, yearDiffLunar(date.year, date.month, date.day), nil) + return []time.Time{d}, nil + } + if date.year < 2400 { + dates := rapidSolarModern(date.year, date.month, date.day, date.leap) + return []time.Time{dates}, nil + } + dates := Solar(date.year, date.month, date.day, date.leap, 8.0) + return []time.Time{dates}, nil + } + + data, err := innerLunar2SolarHanQing(date, nianHaoMap, nil) + if err != nil && err != ERR_NIANHAO_NOT_FOUND { + return data, err + } + if tmp, err := innerLunar2SolarHanQing(date, shuEraMap, shuCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, wuEraMap, wuCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, houQinEraMap, houQinCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, weiZhouSuiEraMap, weiZhouSuiCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, beiLiangEraMap, beiLiangCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, dongWeiBeiQiEraMap, dongWeiBeiQiCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, liaoJinYuanEraMap, liaoJinYuanCals); err == nil { + data = append(data, tmp...) + } + if tmp, err := innerLunar2SolarHanQing(date, nanMingEraMap, nanMingCals); err == nil { + data = append(data, tmp...) + } + return data, nil +} + +func innerLunar2SolarHanQing(data LunarTime, nianHaoMap func() map[string][][]int, options func() map[int]uint32) ([]time.Time, error) { + isGanZhiDay := false + var tgIdx, dzIdex int + if data.ganzhiMonth != "" && data.day == 0 { + //日干支求解,先计算此月的初一,然后根据日干支求解 + isGanZhiDay = true + data.day = 1 + for idx, v := range tiangan { + if strings.HasPrefix(data.ganzhiMonth, v) { + tgIdx = idx + break + } + } + for idx, v := range dizhi { + if strings.HasSuffix(data.ganzhiMonth, v) { + dzIdex = idx + break + } + } + } + years := nianHaoMap()[data.comment] + if len(years) == 0 { + return []time.Time{}, ERR_NIANHAO_NOT_FOUND + } + var res []time.Time + for _, y := range years { + if y[1]-y[0]+1 < data.year { + continue + } + year := y[0] + data.year - 1 + diff := yearDiffLunar(year, data.month, data.day) + //diff!=0且option!=nil时,只有三国时期存在,此时因为蜀汉和吴国都没有改制,所以不进行处理 + if options != nil { + diff = 0 + } + if diff == 255 { + if year == 700 && data.month == 12 { + res = append(res, rapidSolarHan2Qing(year, data.month, data.day, data.leap, 0, options)) + } + data.month = data.month + 2 + if data.month > 12 { + data.month = data.month - 12 + } + if data.month == 3 && strings.Contains(data.desc, "正月") { + data.month = 1 + } + } + if year == 23 && data.comment == "更始" { + diff = 0 + } + res = append(res, rapidSolarHan2Qing(year, data.month, data.day, data.leap, diff, options)) + //当年两个12月 + if year == 239 && data.month == 12 { + res = append(res, rapidSolarHan2Qing(year, data.month, data.day, data.leap, 0, options)) + } + //当年两个4月,5月 + if year == 762 && (data.month == 4 || data.month == 5) { + res = append(res, rapidSolarHan2Qing(year, data.month, data.day, data.leap, 0, options)) + } + } + var realRes []time.Time + for _, v := range res { + if v.IsZero() { + continue + } + if !isGanZhiDay { + realRes = append(realRes, v) + continue + } + //干支日求解 + curTgIdx, curDzIdx := ganZhiOfDayIndex(v) + tgDiff := (tgIdx - curTgIdx + 10) % 10 + dzDiff := (dzIdex - curDzIdx + 12) % 12 + delta := (dzDiff - tgDiff + 12) % 12 + delta2 := delta / 2 + k := (delta2 * 5) % 6 + d := tgDiff + 10*k + if d < 0 { + d += 60 + } + if d > 30 { + continue + } + oldv := v + v = v.Add(time.Duration(d) * 24 * time.Hour) + if v.Year()%100 == 0 && v.Year()%400 != 0 && v.Month() >= 3 && v.Year() < 1582 { + if oldv.Month() < 3 { + v = v.AddDate(0, 0, 1) + } + } + if oldv.Year() == 1582 && ((oldv.Month() == 10 && oldv.Day() <= 4) || oldv.Month() < 10) { + if v.Month() > 10 || (v.Month() == 10 && v.Day() > 4) { + v = v.AddDate(0, 0, 10) + } + } + realRes = append(realRes, v) + } + return realRes, nil +} diff --git a/calendar/chineseLiaoJinYuan.go b/calendar/chineseLiaoJinYuan.go new file mode 100644 index 0000000..d95f992 --- /dev/null +++ b/calendar/chineseLiaoJinYuan.go @@ -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 +} diff --git a/calendar/chineseNanBeiChao.go b/calendar/chineseNanBeiChao.go new file mode 100644 index 0000000..01933c7 --- /dev/null +++ b/calendar/chineseNanBeiChao.go @@ -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 +} diff --git a/calendar/chineseNanMing.go b/calendar/chineseNanMing.go new file mode 100644 index 0000000..1bc590d --- /dev/null +++ b/calendar/chineseNanMing.go @@ -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 +} diff --git a/calendar/chineseSanGuo.go b/calendar/chineseSanGuo.go new file mode 100644 index 0000000..4eee2b4 --- /dev/null +++ b/calendar/chineseSanGuo.go @@ -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 +} diff --git a/calendar/chinese_test.go b/calendar/chinese_test.go index f89ff90..b506cee 100644 --- a/calendar/chinese_test.go +++ b/calendar/chinese_test.go @@ -7,16 +7,20 @@ import ( ) type lunarSolar struct { - Lyear int - Lmonth int - Lday int - Leap bool - Year int - Month int - Day int + Lyear int + Lmonth int + Lday int + Leap bool + Year int + Month 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{ {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}, @@ -40,7 +44,7 @@ func Test_ChineseCalendar(t *testing.T) { for _, v := range testData { { 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 { lyear-- } @@ -49,26 +53,223 @@ func Test_ChineseCalendar(t *testing.T) { 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 { 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-- + /* + { + 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) + } } - 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) - if date.Year() != v.Year || int(date.Month()) != v.Month || date.Day() != v.Day { + date, err := LunarToSolarSingle(v.Lyear, v.Lmonth, v.Lday, v.Leap) + 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) } } + /* + { + 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) + } +} +*/ diff --git a/calendar/era.go b/calendar/era.go new file mode 100644 index 0000000..ed29981 --- /dev/null +++ b/calendar/era.go @@ -0,0 +1,2477 @@ +package calendar + +type Era struct { + //完整农历年的公历年映射 + Year int + Emperor string + Nianhao string + OtherNianHaoStart string + Dynasty string + Offset int +} + +type EraDesc struct { + YearOfNianHao int + Emperor string + Nianhao string + Dynasty string +} + +func (e EraDesc) String() string { + if e.YearOfNianHao == 1 { + return e.Nianhao + "元年" + } + return e.Nianhao + number2Chinese(e.YearOfNianHao, false) + "年" +} + +func innerEras(year int, eraSource func() []Era) []EraDesc { + var eras []Era + eras = eraSource() + var firstEra, secEra, thirdEra Era + for _, v := range eras { + if year < v.Year { + continue + } + if firstEra.Year == secEra.Year && firstEra.OtherNianHaoStart != "" && secEra.OtherNianHaoStart != "" { + thirdEra = v + break + } + if v.OtherNianHaoStart != "" && secEra.Year == 0 && v.Year == year { + secEra = v + continue + } + firstEra = v + if firstEra.Year == secEra.Year && firstEra.OtherNianHaoStart != "" && secEra.OtherNianHaoStart != "" { + continue + } + break + } + var result []EraDesc + nianHao := firstEra.Nianhao + if firstEra.OtherNianHaoStart != "" { + nianHao = firstEra.OtherNianHaoStart + } + result = append(result, EraDesc{ + YearOfNianHao: year - firstEra.Year + 1 + firstEra.Offset, + Emperor: firstEra.Emperor, + Nianhao: nianHao, + Dynasty: firstEra.Dynasty, + }) + nianHao = secEra.Nianhao + if secEra.OtherNianHaoStart != "" { + nianHao = secEra.OtherNianHaoStart + } + if secEra.Year != 0 { + result = append(result, EraDesc{ + YearOfNianHao: year - secEra.Year + 1 + secEra.Offset, + Emperor: secEra.Emperor, + Nianhao: nianHao, + Dynasty: secEra.Dynasty, + }) + } + nianHao = thirdEra.Nianhao + if thirdEra.OtherNianHaoStart != "" { + nianHao = thirdEra.OtherNianHaoStart + } + if thirdEra.Year != 0 { + result = append(result, EraDesc{ + YearOfNianHao: year - thirdEra.Year + 1 + thirdEra.Offset, + Emperor: thirdEra.Emperor, + Nianhao: nianHao, + Dynasty: thirdEra.Dynasty, + }) + } + + return result +} + +func nianHaoMap() map[string][][]int { + return map[string][][]int{ + "民国": [][]int{{1912, 1949}}, + "宣统": [][]int{{1909, 1911}}, + "光绪": [][]int{{1875, 1908}}, + "同治": [][]int{{1862, 1874}}, + "咸丰": [][]int{{1851, 1861}}, + "道光": [][]int{{1821, 1850}}, + "嘉庆": [][]int{{1796, 1820}}, + "乾隆": [][]int{{1736, 1795}}, + "雍正": [][]int{{1723, 1735}}, + "康熙": [][]int{{1662, 1722}}, + "顺治": [][]int{{1644, 1661}}, + "崇祯": [][]int{{1628, 1644}}, + "天启": [][]int{{1621, 1627}}, + "泰昌": [][]int{{1620, 1620}}, + "万历": [][]int{{1573, 1620}}, + "隆庆": [][]int{{1567, 1572}}, + "嘉靖": [][]int{{1522, 1566}}, + "正德": [][]int{{1506, 1521}}, + "弘治": [][]int{{1488, 1505}}, + "成化": [][]int{{1465, 1487}}, + "天顺": [][]int{{1457, 1464}}, + "景泰": [][]int{{1450, 1456}}, + "正统": [][]int{{1436, 1449}}, + "宣德": [][]int{{1426, 1435}}, + "洪熙": [][]int{{1425, 1425}}, + "永乐": [][]int{{1403, 1424}}, + "建文": [][]int{{1399, 1402}}, + "洪武": [][]int{{1368, 1398}}, + "至正": [][]int{{1341, 1368}}, + "元统": [][]int{{1333, 1335}}, + "至顺": [][]int{{1330, 1333}}, + "天历": [][]int{{1328, 1330}}, + "泰定": [][]int{{1324, 1328}}, + "至治": [][]int{{1321, 1323}}, + "延佑": [][]int{{1314, 1320}}, + "皇庆": [][]int{{1312, 1313}}, + "至大": [][]int{{1308, 1311}}, + "大德": [][]int{{1297, 1307}}, + "元贞": [][]int{{1295, 1297}}, + "至元": [][]int{{1264, 1294}, {1335, 1368}}, + "祥兴": [][]int{{1278, 1264}}, + "景炎": [][]int{{1276, 1278}}, + "德佑": [][]int{{1275, 1276}}, + "咸淳": [][]int{{1265, 1275}}, + "景定": [][]int{{1260, 1264}}, + "开庆": [][]int{{1259, 1259}}, + "宝佑": [][]int{{1253, 1258}}, + "淳佑": [][]int{{1241, 1252}}, + "嘉熙": [][]int{{1237, 1240}}, + "端平": [][]int{{1234, 1236}}, + "绍定": [][]int{{1228, 1233}}, + "宝庆": [][]int{{1225, 1227}}, + "嘉定": [][]int{{1208, 1224}}, + "开禧": [][]int{{1205, 1207}}, + "嘉泰": [][]int{{1201, 1204}}, + "庆元": [][]int{{1195, 1200}}, + "绍熙": [][]int{{1190, 1194}}, + "淳熙": [][]int{{1174, 1189}}, + "乾道": [][]int{{1165, 1173}}, + "隆兴": [][]int{{1163, 1164}}, + "绍兴": [][]int{{1131, 1162}}, + "建炎": [][]int{{1127, 1130}}, + "靖康": [][]int{{1126, 1127}}, + "宣和": [][]int{{1119, 1126}}, + "重和": [][]int{{1118, 1119}}, + "政和": [][]int{{1111, 1118}}, + "大观": [][]int{{1107, 1110}}, + "崇宁": [][]int{{1102, 1106}}, + "建中靖国": [][]int{{1101, 1101}}, + "元符": [][]int{{1098, 1100}}, + "绍圣": [][]int{{1094, 1098}}, + "元佑": [][]int{{1086, 1094}}, + "元丰": [][]int{{1078, 1085}}, + "熙宁": [][]int{{1068, 1077}}, + "治平": [][]int{{1064, 1067}}, + "嘉佑": [][]int{{1056, 1063}}, + "至和": [][]int{{1054, 1056}}, + "皇佑": [][]int{{1049, 1054}}, + "庆历": [][]int{{1041, 1048}}, + "康定": [][]int{{1040, 1041}}, + "宝元": [][]int{{1038, 1040}}, + "景佑": [][]int{{1034, 1038}}, + "明道": [][]int{{1032, 1033}}, + "天圣": [][]int{{1023, 1032}}, + "乾兴": [][]int{{1022, 1022}}, + "天禧": [][]int{{1017, 1021}}, + "大中祥符": [][]int{{1008, 1016}}, + "景德": [][]int{{1004, 1007}}, + "咸平": [][]int{{998, 1003}}, + "至道": [][]int{{995, 997}}, + "淳化": [][]int{{990, 994}}, + "端拱": [][]int{{988, 989}}, + "雍熙": [][]int{{984, 987}}, + "太平兴国": [][]int{{976, 984}}, + "开宝": [][]int{{968, 976}}, + "乾德": [][]int{{963, 968}}, + "建隆": [][]int{{960, 963}}, + "显德": [][]int{{954, 960}}, + "广顺": [][]int{{951, 954}}, + "乾佑": [][]int{{948, 950}}, + "开运": [][]int{{944, 948}}, + "天福": [][]int{{936, 944}}, + "清泰": [][]int{{934, 936}}, + "长兴": [][]int{{930, 934}}, + "天成": [][]int{{926, 930}}, + "同光": [][]int{{923, 926}}, + "龙德": [][]int{{921, 923}}, + "贞明": [][]int{{915, 921}}, + "乾化": [][]int{{911, 915}}, + "开平": [][]int{{907, 911}}, + "天佑": [][]int{{904, 907}}, + "天复": [][]int{{901, 904}}, + "光化": [][]int{{898, 901}}, + "乾宁": [][]int{{894, 898}}, + "景福": [][]int{{892, 893}}, + "大顺": [][]int{{890, 891}}, + "龙纪": [][]int{{889, 889}}, + "文德": [][]int{{888, 889}}, + "光启": [][]int{{885, 888}}, + "中和": [][]int{{881, 885}}, + "广明": [][]int{{880, 881}}, + "乾符": [][]int{{874, 880}}, + "咸通": [][]int{{860, 874}}, + "大中": [][]int{{847, 860}}, + "会昌": [][]int{{841, 846}}, + "开成": [][]int{{836, 840}}, + "大和": [][]int{{827, 835}}, + "宝历": [][]int{{825, 827}}, + "长庆": [][]int{{821, 824}}, + "永贞": [][]int{{805, 805}}, + "贞元": [][]int{{785, 805}}, + "兴元": [][]int{{784, 784}}, + "建中": [][]int{{780, 783}}, + "大历": [][]int{{766, 779}}, + "广德": [][]int{{763, 765}}, + "宝应": [][]int{{762, 763}}, + "乾元": [][]int{{758, 760}}, + "天宝": [][]int{{742, 756}}, + "开元": [][]int{{713, 741}}, + "先天": [][]int{{712, 713}}, + "延和": [][]int{{712, 712}}, + "太极": [][]int{{712, 712}}, + "景云": [][]int{{710, 712}}, + "唐隆": [][]int{{710, 710}}, + "景龙": [][]int{{707, 710}}, + "神龙": [][]int{{705, 707}}, + "长安": [][]int{{701, 705}}, + "大足": [][]int{{701, 701}}, + "久视": [][]int{{700, 700}}, + "圣历": [][]int{{698, 700}}, + "万岁通天": [][]int{{696, 697}}, + "万岁登封": [][]int{{696, 696}}, + "天册万岁": [][]int{{695, 695}}, + "证圣": [][]int{{695, 695}}, + "延载": [][]int{{694, 694}}, + "长寿": [][]int{{692, 694}}, + "如意": [][]int{{692, 692}}, + "天授": [][]int{{690, 692}}, + "载初": [][]int{{690, 690}}, + "垂拱": [][]int{{685, 688}}, + "光宅": [][]int{{684, 684}}, + "文明": [][]int{{684, 684}}, + "嗣圣": [][]int{{684, 684}}, + "弘道": [][]int{{683, 683}}, + "永淳": [][]int{{682, 683}}, + "开耀": [][]int{{681, 682}}, + "永隆": [][]int{{680, 681}}, + "调露": [][]int{{679, 680}}, + "仪凤": [][]int{{676, 679}}, + "上元": [][]int{{674, 676}, {760, 762}}, + "咸亨": [][]int{{670, 674}}, + "总章": [][]int{{668, 670}}, + "乾封": [][]int{{666, 668}}, + "麟德": [][]int{{664, 665}}, + "龙朔": [][]int{{661, 663}}, + "显庆": [][]int{{656, 661}}, + "永徽": [][]int{{650, 655}}, + "贞观": [][]int{{627, 649}}, + "武德": [][]int{{618, 626}}, + "义宁": [][]int{{617, 618}}, + "大业": [][]int{{605, 617}}, + "仁寿": [][]int{{601, 604}}, + //special case + "开皇": [][]int{{581, 600}}, + "祯明": [][]int{{587, 589}}, + "至德": [][]int{{583, 586}, {756, 758}}, + "太建": [][]int{{569, 582}}, + "光大": [][]int{{567, 568}}, + "天康": [][]int{{566, 566}}, + "天嘉": [][]int{{560, 566}}, + "永定": [][]int{{557, 559}}, + "太平": [][]int{{556, 557}}, + "绍泰": [][]int{{555, 556}}, + "承圣": [][]int{{552, 555}}, + "大宝": [][]int{{550, 551}}, + "太清": [][]int{{547, 549}}, + "中大同": [][]int{{546, 547}}, + "大同": [][]int{{535, 546}}, + "中大通": [][]int{{529, 534}}, + "大通": [][]int{{527, 529}}, + "普通": [][]int{{520, 527}}, + "天监": [][]int{{502, 519}}, + "中兴": [][]int{{501, 502}}, + "永泰": [][]int{{498, 498}, {765, 766}}, + "永明": [][]int{{483, 494}}, + "升明": [][]int{{477, 479}}, + "元徽": [][]int{{473, 477}}, + "泰豫": [][]int{{472, 472}}, + "大明": [][]int{{457, 465}}, + "孝建": [][]int{{454, 456}}, + "景平": [][]int{{423, 424}}, + "元熙": [][]int{{419, 420}}, + "义熙": [][]int{{405, 419}}, + "大亨": [][]int{{402, 404}}, + "隆安": [][]int{{397, 402}}, + "太元": [][]int{{376, 396}}, + "宁康": [][]int{{373, 375}}, + "咸安": [][]int{{371, 372}}, + "兴宁": [][]int{{363, 365}}, + "隆和": [][]int{{362, 363}}, + "升平": [][]int{{357, 362}}, + "建元": [][]int{{343, 344}, {479, 482}}, + "咸康": [][]int{{335, 342}}, + "咸和": [][]int{{326, 334}}, + "太宁": [][]int{{323, 326}}, + "永昌": [][]int{{322, 323}, {689, 689}}, + "大兴": [][]int{{318, 322}}, + "建兴": [][]int{{313, 317}}, + "光熙": [][]int{{306, 306}}, + "太安": [][]int{{302, 304}}, + "永熙": [][]int{{290, 291}}, + "太康": [][]int{{280, 290}}, + "咸宁": [][]int{{275, 280}}, + "泰始": [][]int{{265, 274}, {465, 472}}, + "咸熙": [][]int{{264, 265}}, + "景元": [][]int{{260, 264}}, + "正元": [][]int{{254, 256}}, + "嘉平": [][]int{{249, 254}}, + "正始": [][]int{{240, 249}}, + "景初": [][]int{{237, 239}}, + "青龙": [][]int{{233, 237}}, + "太和": [][]int{{227, 233}, {366, 371}}, + "黄初": [][]int{{220, 226}}, + "延康": [][]int{{220, 220}}, + "建安": [][]int{{196, 220}}, + "兴平": [][]int{{194, 195}}, + "初平": [][]int{{190, 193}}, + "中平": [][]int{{184, 189}}, + "光和": [][]int{{178, 184}}, + "熹平": [][]int{{172, 178}}, + "建宁": [][]int{{168, 172}}, + "永康": [][]int{{167, 167}, {300, 301}}, + "延熹": [][]int{{158, 167}}, + "永寿": [][]int{{155, 158}}, + "永兴": [][]int{{153, 154}, {304, 306}}, + "元嘉": [][]int{{151, 153}, {424, 453}}, + "和平": [][]int{{150, 150}}, + "建和": [][]int{{147, 149}}, + "本初": [][]int{{146, 146}}, + "永嘉": [][]int{{145, 145}, {307, 313}}, + "建康": [][]int{{144, 144}}, + "汉安": [][]int{{142, 144}}, + "永和": [][]int{{136, 141}, {345, 356}}, + "阳嘉": [][]int{{132, 135}}, + "永建": [][]int{{126, 132}}, + "延光": [][]int{{122, 125}}, + "建光": [][]int{{121, 122}}, + "永宁": [][]int{{120, 121}, {301, 302}}, + "元初": [][]int{{114, 120}}, + "永初": [][]int{{107, 113}, {420, 423}}, + "延平": [][]int{{106, 106}}, + "元兴": [][]int{{105, 106}}, + "永元": [][]int{{89, 105}, {499, 501}}, + "章和": [][]int{{87, 88}}, + "元和": [][]int{{84, 87}, {806, 820}}, + "建初": [][]int{{76, 84}}, + "永平": [][]int{{58, 75}}, + "建武中元": [][]int{{56, 57}}, + "建武": [][]int{{25, 56}, {317, 318}, {494, 498}}, + "更始": [][]int{{23, 25}}, + "地皇": [][]int{{20, 23}}, + "天凤": [][]int{{14, 19}}, + "始建国": [][]int{{9, 13}}, + "初始": [][]int{{8, 8}}, + "居摄": [][]int{{6, 8}}, + "元始": [][]int{{1, 5}}, + "元寿": [][]int{{-1, 0}}, + "建平": [][]int{{-5, -2}}, + "绥和": [][]int{{-7, -6}}, + "元延": [][]int{{-11, -8}}, + "永始": [][]int{{-15, -12}}, + "鸿嘉": [][]int{{-19, -16}}, + "阳朔": [][]int{{-23, -20}}, + "河平": [][]int{{-27, -24}}, + "建始": [][]int{{-31, -27}}, + "竟宁": [][]int{{-32, -32}}, + "建昭": [][]int{{-37, -33}}, + "永光": [][]int{{-42, -38}}, + "初元": [][]int{{-47, -43}}, + "黄龙": [][]int{{-48, -48}}, + "甘露": [][]int{{-52, -49}, {256, 260}}, + "五凤": [][]int{{-56, -53}}, + "神爵": [][]int{{-60, -57}}, + "元康": [][]int{{-64, -60}, {291, 300}}, + "地节": [][]int{{-68, -65}}, + "本始": [][]int{{-72, -69}}, + "元平": [][]int{{-73, -73}}, + "元凤": [][]int{{-79, -74}}, + "始元": [][]int{{-85, -79}}, + "后元": [][]int{{-87, -86}}, + "征和": [][]int{{-91, -88}}, + "太始": [][]int{{-95, -92}}, + "天汉": [][]int{{-99, -96}}, + "太初": [][]int{{-103, -100}}, + } +} + +func hanEras() []Era { + return []Era{ + { + Year: 220, + Emperor: "魏文帝", + OtherNianHaoStart: "黄初", + Dynasty: "魏", + }, + { + Year: 220, + Emperor: "汉献帝", + OtherNianHaoStart: "延康", + Dynasty: "东汉", + }, + { + Year: 196, + Emperor: "汉献帝", + Nianhao: "建安", + Dynasty: "东汉", + }, + { + Year: 194, + Emperor: "汉献帝", + Nianhao: "兴平", + Dynasty: "东汉", + }, + { + Year: 190, + Emperor: "汉献帝", + Nianhao: "初平", + Dynasty: "东汉", + }, + { + Year: 184, + Emperor: "汉灵帝", + OtherNianHaoStart: "中平", + Dynasty: "东汉", + }, + { + Year: 178, + Emperor: "汉灵帝", + OtherNianHaoStart: "光和", + Dynasty: "东汉", + }, + { + Year: 172, + Emperor: "汉灵帝", + OtherNianHaoStart: "熹平", + Dynasty: "东汉", + }, + { + Year: 168, + Emperor: "汉灵帝", + Nianhao: "建宁", + Dynasty: "东汉", + }, + { + Year: 167, + Emperor: "汉桓帝", + OtherNianHaoStart: "永康", + Dynasty: "东汉", + }, + { + Year: 158, + Emperor: "汉桓帝", + OtherNianHaoStart: "延熹", + Dynasty: "东汉", + }, + { + Year: 155, + Emperor: "汉桓帝", + Nianhao: "永寿", + Dynasty: "东汉", + }, + { + Year: 153, + Emperor: "汉桓帝", + OtherNianHaoStart: "永兴", + Dynasty: "东汉", + }, + { + Year: 151, + Emperor: "汉桓帝", + Nianhao: "元嘉", + Dynasty: "东汉", + }, + { + Year: 150, + Emperor: "汉桓帝", + Nianhao: "和平", + Dynasty: "东汉", + }, + { + Year: 147, + Emperor: "汉桓帝", + Nianhao: "建和", + Dynasty: "东汉", + }, + { + Year: 146, + Emperor: "汉质帝", + Nianhao: "本初", + Dynasty: "东汉", + }, + { + Year: 145, + Emperor: "汉冲帝", + Nianhao: "永嘉", + Dynasty: "东汉", + }, + { + Year: 144, + Emperor: "汉顺帝", + OtherNianHaoStart: "建康", + Dynasty: "东汉", + }, + { + Year: 142, + Emperor: "汉顺帝", + Nianhao: "汉安", + Dynasty: "东汉", + }, + { + Year: 136, + Emperor: "汉顺帝", + Nianhao: "永和", + Dynasty: "东汉", + }, + { + Year: 132, + Emperor: "汉顺帝", + OtherNianHaoStart: "阳嘉", + Dynasty: "东汉", + }, + { + Year: 126, + Emperor: "汉顺帝", + Nianhao: "永建", + Dynasty: "东汉", + }, + { + Year: 122, + Emperor: "汉安帝", + OtherNianHaoStart: "延光", + Dynasty: "东汉", + }, + { + Year: 121, + Emperor: "汉安帝", + OtherNianHaoStart: "建光", + Dynasty: "东汉", + }, + { + Year: 120, + Emperor: "汉安帝", + OtherNianHaoStart: "永宁", + Dynasty: "东汉", + }, + { + Year: 114, + Emperor: "汉安帝", + Nianhao: "元初", + Dynasty: "东汉", + }, + { + Year: 107, + Emperor: "汉安帝", + Nianhao: "永初", + Dynasty: "东汉", + }, + { + Year: 106, + Emperor: "汉殇帝", + OtherNianHaoStart: "延平", + Dynasty: "东汉", + }, + { + Year: 105, + Emperor: "汉和帝", + OtherNianHaoStart: "元兴", + Dynasty: "东汉", + }, + { + Year: 89, + Emperor: "汉和帝", + Nianhao: "永元", + Dynasty: "东汉", + }, + { + Year: 87, + Emperor: "汉章帝", + OtherNianHaoStart: "章和", + Dynasty: "东汉", + }, + { + Year: 84, + Emperor: "汉章帝", + OtherNianHaoStart: "元和", + Dynasty: "东汉", + }, + { + Year: 76, + Emperor: "汉章帝", + Nianhao: "建初", + Dynasty: "东汉", + }, + { + Year: 58, + Emperor: "汉明帝", + Nianhao: "永平", + Dynasty: "东汉", + }, + { + Year: 56, + Emperor: "汉光武帝", + OtherNianHaoStart: "建武中元", + Dynasty: "东汉", + }, + { + Year: 25, + Emperor: "汉光武帝", + OtherNianHaoStart: "建武", + Dynasty: "东汉", + }, + { + Year: 23, + Emperor: "汉更始帝", + OtherNianHaoStart: "更始", + Dynasty: "汉", + }, + { + Year: 20, + Emperor: "新王莽", + Nianhao: "地皇", + Dynasty: "新", + }, + { + Year: 14, + Emperor: "新王莽", + Nianhao: "天凤", + Dynasty: "新", + }, + { + Year: 9, + Emperor: "新王莽", + Nianhao: "始建国", + Dynasty: "新", + }, + { + Year: 8, + Emperor: "汉平帝", + OtherNianHaoStart: "初始", + Dynasty: "西汉", + }, + { + Year: 6, + Emperor: "汉平帝", + Nianhao: "居摄", + Dynasty: "西汉", + }, + { + Year: 1, + Emperor: "汉平帝", + Nianhao: "元始", + Dynasty: "西汉", + }, + { + Year: -1, + Emperor: "汉哀帝", + Nianhao: "元寿", + Dynasty: "西汉", + }, + { + Year: -5, + Emperor: "汉哀帝", + Nianhao: "建平", + Dynasty: "西汉", + }, + { + Year: -7, + Emperor: "汉成帝", + Nianhao: "绥和", + Dynasty: "西汉", + }, + { + Year: -11, + Emperor: "汉成帝", + Nianhao: "元延", + Dynasty: "西汉", + }, + { + Year: -15, + Emperor: "汉成帝", + Nianhao: "永始", + Dynasty: "西汉", + }, + { + Year: -19, + Emperor: "汉成帝", + Nianhao: "鸿嘉", + Dynasty: "西汉", + }, + { + Year: -23, + Emperor: "汉成帝", + Nianhao: "阳朔", + Dynasty: "西汉", + }, + { + Year: -27, + Emperor: "汉成帝", + OtherNianHaoStart: "河平", + Dynasty: "西汉", + }, + { + Year: -31, + Emperor: "汉成帝", + Nianhao: "建始", + Dynasty: "西汉", + }, + { + Year: -32, + Emperor: "汉元帝", + Nianhao: "竟宁", + Dynasty: "西汉", + }, + { + Year: -37, + Emperor: "汉元帝", + Nianhao: "建昭", + Dynasty: "西汉", + }, + { + Year: -42, + Emperor: "汉元帝", + Nianhao: "永光", + Dynasty: "西汉", + }, + { + Year: -47, + Emperor: "汉元帝", + Nianhao: "初元", + Dynasty: "西汉", + }, + { + Year: -48, + Emperor: "汉宣帝", + Nianhao: "黄龙", + Dynasty: "西汉", + }, + { + Year: -52, + Emperor: "汉宣帝", + Nianhao: "甘露", + Dynasty: "西汉", + }, + { + Year: -56, + Emperor: "汉宣帝", + Nianhao: "五凤", + Dynasty: "西汉", + }, + { + Year: -60, + Emperor: "汉宣帝", + OtherNianHaoStart: "神爵", + Dynasty: "西汉", + }, + { + Year: -64, + Emperor: "汉宣帝", + Nianhao: "元康", + Dynasty: "西汉", + }, + { + Year: -68, + Emperor: "汉宣帝", + Nianhao: "地节", + Dynasty: "西汉", + }, + { + Year: -72, + Emperor: "汉宣帝", + Nianhao: "本始", + Dynasty: "西汉", + }, + { + Year: -73, + Emperor: "汉昭帝", + Nianhao: "元平", + Dynasty: "西汉", + }, + { + Year: -79, + Emperor: "汉昭帝", + OtherNianHaoStart: "元凤", + Dynasty: "西汉", + }, + { + Year: -85, + Emperor: "汉昭帝", + Nianhao: "始元", + Dynasty: "西汉", + }, + { + Year: -87, + Emperor: "汉武帝", + Nianhao: "后元", + Dynasty: "西汉", + }, + { + Year: -91, + Emperor: "汉武帝", + Nianhao: "征和", + Dynasty: "西汉", + }, + { + Year: -95, + Emperor: "汉武帝", + Nianhao: "太始", + Dynasty: "西汉", + }, + { + Year: -99, + Emperor: "汉武帝", + Nianhao: "天汉", + Dynasty: "西汉", + }, + { + Year: -103, + Emperor: "汉武帝", + Nianhao: "太初", + Dynasty: "西汉", + }, + } +} + +func weiJinNanBeiChaoEras() []Era { + return []Era{ + { + Year: 617, + Emperor: "隋恭帝", + OtherNianHaoStart: "义宁", + Dynasty: "隋", + }, + { + Year: 605, + Emperor: "隋炀帝", + Nianhao: "大业", + Dynasty: "隋", + }, + { + Year: 601, + Emperor: "隋文帝", + Nianhao: "仁寿", + Dynasty: "隋", + }, + { + Year: 589, + Emperor: "隋文帝", + Nianhao: "开皇", + Dynasty: "隋", + Offset: 8, + }, + { + Year: 587, + Emperor: "陈后主", + Nianhao: "祯明", + Dynasty: "南朝陈", + }, + { + Year: 583, + Emperor: "陈后主", + Nianhao: "至德", + Dynasty: "南朝陈", + }, + { + Year: 569, + Emperor: "陈宣帝", + Nianhao: "太建", + Dynasty: "南朝陈", + }, + { + Year: 567, + Emperor: "陈伯宗", + Nianhao: "光大", + Dynasty: "南朝陈", + }, + { + Year: 566, + Emperor: "陈文帝", + OtherNianHaoStart: "天康", + Dynasty: "南朝陈", + }, + { + Year: 560, + Emperor: "陈文帝", + Nianhao: "天嘉", + Dynasty: "南朝陈", + }, + { + Year: 557, + Emperor: "陈武帝", + OtherNianHaoStart: "永定", + Dynasty: "南朝陈", + }, + { + Year: 556, + Emperor: "梁敬帝", + OtherNianHaoStart: "太平", + Dynasty: "南朝梁", + }, + { + Year: 555, + Emperor: "梁敬帝", + OtherNianHaoStart: "绍泰", + Dynasty: "南朝梁", + }, + { + Year: 552, + Emperor: "梁元帝", + Nianhao: "承圣", + Dynasty: "南朝梁", + }, + { + Year: 550, + Emperor: "梁简文帝", + Nianhao: "大宝", + Dynasty: "南朝梁", + }, + { + Year: 547, + Emperor: "梁武帝", + OtherNianHaoStart: "太清", + Dynasty: "南朝梁", + }, + { + Year: 546, + Emperor: "梁武帝", + OtherNianHaoStart: "中大同", + Dynasty: "南朝梁", + }, + { + Year: 535, + Emperor: "梁武帝", + Nianhao: "大同", + Dynasty: "南朝梁", + }, + { + Year: 529, + Emperor: "梁武帝", + OtherNianHaoStart: "中大通", + Dynasty: "南朝梁", + }, + { + Year: 527, + Emperor: "梁武帝", + OtherNianHaoStart: "大通", + Dynasty: "南朝梁", + }, + { + Year: 520, + Emperor: "梁武帝", + Nianhao: "普通", + Dynasty: "南朝梁", + }, + { + Year: 502, + Emperor: "梁武帝", + OtherNianHaoStart: "天监", + Dynasty: "南朝梁", + }, + { + Year: 501, + Emperor: "齐和帝", + OtherNianHaoStart: "中兴", + Dynasty: "南朝齐", + }, + { + Year: 499, + Emperor: "齐东昏侯", + Nianhao: "永元", + Dynasty: "南朝齐", + }, + { + Year: 498, + Emperor: "齐明帝", + OtherNianHaoStart: "永泰", + Dynasty: "南朝齐", + }, + { + Year: 494, + Emperor: "齐明帝", + OtherNianHaoStart: "建武", + Dynasty: "南朝齐", + }, + { + Year: 483, + Emperor: "齐武帝", + Nianhao: "永明", + Dynasty: "南朝齐", + }, + { + Year: 479, + Emperor: "齐高帝", + OtherNianHaoStart: "建元", + Dynasty: "南朝齐", + }, + { + Year: 477, + Emperor: "宋顺帝", + OtherNianHaoStart: "升明", + Dynasty: "南朝宋", + }, + { + Year: 473, + Emperor: "宋后废帝", + Nianhao: "元徽", + Dynasty: "南朝宋", + }, + { + Year: 472, + Emperor: "宋明帝", + OtherNianHaoStart: "泰豫", + Dynasty: "南朝宋", + }, + { + Year: 465, + Emperor: "宋明帝", + OtherNianHaoStart: "泰始", + Dynasty: "南朝宋", + }, + { + Year: 457, + Emperor: "宋孝武帝", + Nianhao: "大明", + Dynasty: "南朝宋", + }, + { + Year: 454, + Emperor: "宋孝武帝", + Nianhao: "孝建", + Dynasty: "南朝宋", + }, + { + Year: 424, + Emperor: "宋文帝", + OtherNianHaoStart: "元嘉", + Dynasty: "南朝宋", + }, + { + Year: 423, + Emperor: "宋少帝", + OtherNianHaoStart: "景平", + Dynasty: "南朝宋", + }, + { + Year: 420, + Emperor: "宋武帝", + OtherNianHaoStart: "永初", + Dynasty: "南朝宋", + }, + { + Year: 419, + Emperor: "晋恭帝", + OtherNianHaoStart: "元熙", + Dynasty: "东晋", + }, + { + Year: 405, + Emperor: "晋安帝", + Nianhao: "义熙", + Dynasty: "东晋", + }, + { + Year: 402, + Emperor: "晋安帝", + OtherNianHaoStart: "大亨", + Dynasty: "东晋", + }, + { + Year: 397, + Emperor: "晋安帝", + Nianhao: "隆安", + Dynasty: "东晋", + }, + { + Year: 376, + Emperor: "晋孝武帝", + Nianhao: "太元", + Dynasty: "东晋", + }, + { + Year: 373, + Emperor: "晋孝武帝", + Nianhao: "宁康", + Dynasty: "东晋", + }, + { + Year: 371, + Emperor: "晋简文帝", + OtherNianHaoStart: "咸安", + Dynasty: "东晋", + }, + { + Year: 366, + Emperor: "晋废帝", + Nianhao: "太和", + Dynasty: "东晋", + }, + { + Year: 363, + Emperor: "晋哀帝", + OtherNianHaoStart: "兴宁", + Dynasty: "东晋", + }, + { + Year: 362, + Emperor: "晋哀帝", + OtherNianHaoStart: "隆和", + Dynasty: "东晋", + }, + { + Year: 357, + Emperor: "晋穆帝", + Nianhao: "升平", + Dynasty: "东晋", + }, + { + Year: 345, + Emperor: "晋穆帝", + Nianhao: "永和", + Dynasty: "东晋", + }, + { + Year: 343, + Emperor: "晋康帝", + Nianhao: "建元", + Dynasty: "东晋", + }, + { + Year: 335, + Emperor: "晋成帝", + Nianhao: "咸康", + Dynasty: "东晋", + }, + { + Year: 326, + Emperor: "晋成帝", + OtherNianHaoStart: "咸和", + Dynasty: "东晋", + }, + { + Year: 323, + Emperor: "晋明帝", + OtherNianHaoStart: "太宁", + Dynasty: "东晋", + }, + { + Year: 322, + Emperor: "晋元帝", + OtherNianHaoStart: "永昌", + Dynasty: "东晋", + }, + { + Year: 318, + Emperor: "晋元帝", + OtherNianHaoStart: "大兴", + Dynasty: "东晋", + }, + { + Year: 317, + Emperor: "晋元帝", + OtherNianHaoStart: "建武", + Dynasty: "东晋", + }, + { + Year: 313, + Emperor: "晋愍帝", + OtherNianHaoStart: "建兴", + Dynasty: "西晋", + }, + { + Year: 307, + Emperor: "晋怀帝", + Nianhao: "永嘉", + Dynasty: "西晋", + }, + { + Year: 306, + Emperor: "晋惠帝", + OtherNianHaoStart: "光熙", + Dynasty: "西晋", + }, + { + Year: 304, + Emperor: "晋惠帝", + OtherNianHaoStart: "永兴", + }, + { + Year: 302, + Emperor: "晋惠帝", + OtherNianHaoStart: "太安", + Dynasty: "西晋", + }, + { + Year: 301, + Emperor: "晋惠帝", + OtherNianHaoStart: "永宁", + Dynasty: "西晋", + }, + { + Year: 300, + Emperor: "晋惠帝", + OtherNianHaoStart: "永康", + Dynasty: "西晋", + }, + { + Year: 291, + Emperor: "晋惠帝", + OtherNianHaoStart: "元康", + Dynasty: "西晋", + }, + { + Year: 290, + Emperor: "晋惠帝", + OtherNianHaoStart: "永熙", + Dynasty: "西晋", + }, + { + Year: 280, + Emperor: "晋武帝", + OtherNianHaoStart: "太康", + Dynasty: "西晋", + }, + { + Year: 275, + Emperor: "晋武帝", + Nianhao: "咸宁", + Dynasty: "西晋", + }, + { + Year: 265, + Emperor: "晋武帝", + OtherNianHaoStart: "泰始", + Dynasty: "西晋", + }, + { + Year: 264, + Emperor: "魏元帝", + OtherNianHaoStart: "咸熙", + Dynasty: "魏", + }, + { + Year: 260, + Emperor: "魏元帝", + OtherNianHaoStart: "景元", + Dynasty: "魏", + }, + { + Year: 256, + Emperor: "魏少帝", + OtherNianHaoStart: "甘露", + Dynasty: "魏", + }, + { + Year: 254, + Emperor: "魏少帝", + OtherNianHaoStart: "正元", + Dynasty: "魏", + }, + { + Year: 249, + Emperor: "魏少帝", + OtherNianHaoStart: "嘉平", + Dynasty: "魏", + }, + { + Year: 240, + Emperor: "魏少帝", + Nianhao: "正始", + Dynasty: "魏", + }, + { + Year: 237, + Emperor: "魏明帝", + OtherNianHaoStart: "景初", + Dynasty: "魏", + }, + { + Year: 233, + Emperor: "魏明帝", + OtherNianHaoStart: "青龙", + Dynasty: "魏", + }, + { + Year: 227, + Emperor: "魏明帝", + Nianhao: "太和", + Dynasty: "魏", + }, + { + Year: 220, + Emperor: "魏文帝", + OtherNianHaoStart: "黄初", + Dynasty: "魏", + }, + { + Year: 220, + Emperor: "汉献帝", + Nianhao: "延康", + Dynasty: "东汉", + }, + } +} + +func tangEras() []Era { + return []Era{ + { + Year: 904, + Emperor: "唐哀帝", + OtherNianHaoStart: "天佑", + Dynasty: "唐", + }, + { + Year: 901, + Emperor: "唐昭宗", + OtherNianHaoStart: "天复", + Dynasty: "唐", + }, + { + Year: 898, + Emperor: "唐昭宗", + OtherNianHaoStart: "光化", + Dynasty: "唐", + }, + { + Year: 894, + Emperor: "唐昭宗", + Nianhao: "乾宁", + Dynasty: "唐", + }, + { + Year: 892, + Emperor: "唐昭宗", + Nianhao: "景福", + Dynasty: "唐", + }, + { + Year: 890, + Emperor: "唐昭宗", + Nianhao: "大顺", + Dynasty: "唐", + }, + { + Year: 889, + Emperor: "唐昭宗", + OtherNianHaoStart: "龙纪", + Dynasty: "唐", + }, + { + Year: 888, + Emperor: "唐昭宗", + OtherNianHaoStart: "文德", + Dynasty: "唐", + }, + { + Year: 885, + Emperor: "唐僖宗", + OtherNianHaoStart: "光启", + Dynasty: "唐", + }, + { + Year: 881, + Emperor: "唐僖宗", + OtherNianHaoStart: "中和", + Dynasty: "唐", + }, + { + Year: 880, + Emperor: "唐僖宗", + OtherNianHaoStart: "广明", + Dynasty: "唐", + }, + { + Year: 874, + Emperor: "唐僖宗", + OtherNianHaoStart: "乾符", + Dynasty: "唐", + }, + { + Year: 860, + Emperor: "唐懿宗", + OtherNianHaoStart: "咸通", + Dynasty: "唐", + }, + { + Year: 847, + Emperor: "唐宣宗", + Nianhao: "大中", + Dynasty: "唐", + }, + { + Year: 841, + Emperor: "唐武宗", + Nianhao: "会昌", + Dynasty: "唐", + }, + { + Year: 836, + Emperor: "唐文宗", + Nianhao: "开成", + Dynasty: "唐", + }, + { + Year: 827, + Emperor: "唐文宗", + OtherNianHaoStart: "大和", + Dynasty: "唐", + }, + { + Year: 825, + Emperor: "唐敬宗", + Nianhao: "宝历", + Dynasty: "唐", + }, + { + Year: 821, + Emperor: "唐穆宗", + Nianhao: "长庆", + Dynasty: "唐", + }, + { + Year: 806, + Emperor: "唐宪宗", + Nianhao: "元和", + Dynasty: "唐", + }, + { + Year: 805, + Emperor: "唐顺宗", + OtherNianHaoStart: "永贞", + Dynasty: "唐", + }, + { + Year: 785, + Emperor: "唐德宗", + Nianhao: "贞元", + Dynasty: "唐", + }, + { + Year: 784, + Emperor: "唐德宗", + Nianhao: "兴元", + Dynasty: "唐", + }, + { + Year: 780, + Emperor: "唐德宗", + Nianhao: "建中", + Dynasty: "唐", + }, + { + Year: 766, + Emperor: "唐代宗", + OtherNianHaoStart: "大历", + Dynasty: "唐", + }, + { + Year: 765, + Emperor: "唐代宗", + OtherNianHaoStart: "永泰", + Dynasty: "唐", + }, + { + Year: 763, + Emperor: "唐代宗", + OtherNianHaoStart: "广德", + Dynasty: "唐", + }, + { + Year: 762, + Emperor: "唐代宗", + OtherNianHaoStart: "宝应", + Dynasty: "唐", + }, + { + Year: 760, + Emperor: "唐肃宗", + OtherNianHaoStart: "上元", + Dynasty: "唐", + }, + { + Year: 758, + Emperor: "唐肃宗", + OtherNianHaoStart: "乾元", + Dynasty: "唐", + }, + { + Year: 756, + Emperor: "唐肃宗", + OtherNianHaoStart: "至德", + Dynasty: "唐", + }, + { + Year: 742, + Emperor: "唐玄宗", + Nianhao: "天宝", + Dynasty: "唐", + }, + { + Year: 713, + Emperor: "唐玄宗", + OtherNianHaoStart: "开元", + Dynasty: "唐", + }, + { + Year: 712, + Emperor: "唐玄宗", + OtherNianHaoStart: "先天", + Dynasty: "唐", + }, + { + Year: 712, + Emperor: "唐睿宗", + OtherNianHaoStart: "延和", + Dynasty: "唐", + }, + { + Year: 712, + Emperor: "唐睿宗", + OtherNianHaoStart: "太极", + Dynasty: "唐", + }, + { + Year: 710, + Emperor: "唐睿宗", + OtherNianHaoStart: "景云", + Dynasty: "唐", + }, + { + Year: 710, + Emperor: "唐殇帝", + OtherNianHaoStart: "唐隆", + Dynasty: "唐", + }, + { + Year: 707, + Emperor: "唐中宗", + OtherNianHaoStart: "景龙", + Dynasty: "唐", + }, + { + Year: 705, + Emperor: "唐中宗", + OtherNianHaoStart: "神龙", + Dynasty: "唐", + }, + { + Year: 701, + Emperor: "武则天", + OtherNianHaoStart: "长安", + Dynasty: "武周", + }, + { + Year: 701, + Emperor: "武则天", + Nianhao: "大足", + Dynasty: "武周", + }, + { + Year: 700, + Emperor: "武则天", + OtherNianHaoStart: "久视", + Dynasty: "武周", + }, + { + Year: 698, + Emperor: "武则天", + Nianhao: "圣历", + Dynasty: "武周", + }, + { + Year: 696, + Emperor: "武则天", + OtherNianHaoStart: "万岁通天", + Dynasty: "武周", + }, + { + Year: 696, + Emperor: "武则天", + Nianhao: "万岁登封", + Dynasty: "武周", + }, + { + Year: 695, + Emperor: "武则天", + OtherNianHaoStart: "天册万岁", + Dynasty: "武周", + }, + { + Year: 695, + Emperor: "武则天", + Nianhao: "证圣", + Dynasty: "武周", + }, + { + Year: 694, + Emperor: "武则天", + OtherNianHaoStart: "延载", + Dynasty: "武周", + }, + { + Year: 692, + Emperor: "武则天", + OtherNianHaoStart: "长寿", + Dynasty: "武周", + }, + { + Year: 692, + Emperor: "武则天", + OtherNianHaoStart: "如意", + Dynasty: "武周", + }, + { + Year: 690, + Emperor: "武则天", + OtherNianHaoStart: "天授", + Dynasty: "武周", + }, + { + Year: 690, + Emperor: "唐睿宗", + Nianhao: "载初", + Dynasty: "唐", + }, + { + Year: 689, + Emperor: "唐睿宗", + Nianhao: "永昌", + Dynasty: "唐", + }, + { + Year: 685, + Emperor: "唐睿宗", + Nianhao: "垂拱", + Dynasty: "唐", + }, + { + Year: 684, + Emperor: "唐睿宗", + OtherNianHaoStart: "光宅", + Dynasty: "唐", + }, + { + Year: 684, + Emperor: "唐睿宗", + OtherNianHaoStart: "文明", + Dynasty: "唐", + }, + { + Year: 684, + Emperor: "唐中宗", + Nianhao: "嗣圣", + Dynasty: "唐", + }, + { + Year: 683, + Emperor: "唐高宗", + OtherNianHaoStart: "弘道", + Dynasty: "唐", + }, + { + Year: 682, + Emperor: "唐高宗", + OtherNianHaoStart: "永淳", + Dynasty: "唐", + }, + { + Year: 681, + Emperor: "唐高宗", + OtherNianHaoStart: "开耀", + Dynasty: "唐", + }, + { + Year: 680, + Emperor: "唐高宗", + OtherNianHaoStart: "永隆", + Dynasty: "唐", + }, + { + Year: 679, + Emperor: "唐高宗", + OtherNianHaoStart: "调露", + Dynasty: "唐", + }, + { + Year: 676, + Emperor: "唐高宗", + OtherNianHaoStart: "仪凤", + Dynasty: "唐", + }, + { + Year: 674, + Emperor: "唐高宗", + OtherNianHaoStart: "上元", + Dynasty: "唐", + }, + { + Year: 670, + Emperor: "唐高宗", + OtherNianHaoStart: "咸亨", + Dynasty: "唐", + }, + { + Year: 668, + Emperor: "唐高宗", + OtherNianHaoStart: "总章", + Dynasty: "唐", + }, + { + Year: 666, + Emperor: "唐高宗", + Nianhao: "乾封", + Dynasty: "唐", + }, + { + Year: 664, + Emperor: "唐高宗", + Nianhao: "麟德", + Dynasty: "唐", + }, + { + Year: 661, + Emperor: "唐高宗", + OtherNianHaoStart: "龙朔", + Dynasty: "唐", + }, + { + Year: 656, + Emperor: "唐高宗", + Nianhao: "显庆", + Dynasty: "唐", + }, + { + Year: 650, + Emperor: "唐高宗", + Nianhao: "永徽", + Dynasty: "唐", + }, + { + Year: 627, + Emperor: "唐太宗", + Nianhao: "贞观", + Dynasty: "唐", + }, + { + Year: 618, + Emperor: "唐高祖", + OtherNianHaoStart: "武德", + Dynasty: "唐", + }, + { + Year: 617, + Emperor: "隋恭帝", + Nianhao: "义宁", + Dynasty: "隋", + }, + } +} + +func wudaiSongYuanEras() []Era { + return []Era{ + { + Year: 1341, + Emperor: "元顺帝", + Nianhao: "至正", + Dynasty: "元", + }, + { + Year: 1335, + Emperor: "元顺帝", + OtherNianHaoStart: "至元", + Dynasty: "元", + }, + { + Year: 1333, + Emperor: "元顺帝", + OtherNianHaoStart: "元统", + Dynasty: "元", + }, + { + Year: 1330, + Emperor: "元文宗", + OtherNianHaoStart: "至顺", + Dynasty: "元", + }, + { + Year: 1328, + Emperor: "元文宗", + OtherNianHaoStart: "天历", + Dynasty: "元", + }, + { + Year: 1324, + Emperor: "元泰定帝", + Nianhao: "泰定", + Dynasty: "元", + }, + { + Year: 1321, + Emperor: "元英宗", + Nianhao: "至治", + Dynasty: "元", + }, + { + Year: 1314, + Emperor: "元仁宗", + Nianhao: "延佑", + Dynasty: "元", + }, + { + Year: 1312, + Emperor: "元仁宗", + Nianhao: "皇庆", + Dynasty: "元", + }, + { + Year: 1308, + Emperor: "元武宗", + Nianhao: "至大", + Dynasty: "元", + }, + { + Year: 1297, + Emperor: "元成宗", + OtherNianHaoStart: "大德", + Dynasty: "元", + }, + { + Year: 1295, + Emperor: "元成宗", + Nianhao: "元贞", + Dynasty: "元", + }, + { + Year: 1279, + Emperor: "元世祖", + OtherNianHaoStart: "至元", + Dynasty: "元", + Offset: 15, + }, + { + Year: 1278, + Emperor: "宋帝昺", + OtherNianHaoStart: "祥兴", + Dynasty: "宋", + }, + { + Year: 1276, + Emperor: "宋端宗", + OtherNianHaoStart: "景炎", + Dynasty: "宋", + }, + { + Year: 1275, + Emperor: "宋恭帝", + OtherNianHaoStart: "德佑", + Dynasty: "宋", + }, + { + Year: 1265, + Emperor: "宋度宗", + Nianhao: "咸淳", + Dynasty: "宋", + }, + { + Year: 1260, + Emperor: "宋理宗", + Nianhao: "景定", + Dynasty: "宋", + }, + { + Year: 1259, + Emperor: "宋理宗", + Nianhao: "开庆", + Dynasty: "宋", + }, + { + Year: 1253, + Emperor: "宋理宗", + Nianhao: "宝佑", + Dynasty: "宋", + }, + { + Year: 1241, + Emperor: "宋理宗", + Nianhao: "淳佑", + Dynasty: "宋", + }, + { + Year: 1237, + Emperor: "宋理宗", + Nianhao: "嘉熙", + Dynasty: "宋", + }, + { + Year: 1234, + Emperor: "宋理宗", + Nianhao: "端平", + Dynasty: "宋", + }, + { + Year: 1228, + Emperor: "宋理宗", + Nianhao: "绍定", + Dynasty: "宋", + }, + { + Year: 1225, + Emperor: "宋理宗", + Nianhao: "宝庆", + Dynasty: "宋", + }, + { + Year: 1208, + Emperor: "宋宁宗", + Nianhao: "嘉定", + Dynasty: "宋", + }, + { + Year: 1205, + Emperor: "宋宁宗", + Nianhao: "开禧", + Dynasty: "宋", + }, + { + Year: 1201, + Emperor: "宋宁宗", + Nianhao: "嘉泰", + Dynasty: "宋", + }, + { + Year: 1195, + Emperor: "宋宁宗", + Nianhao: "庆元", + Dynasty: "宋", + }, + { + Year: 1190, + Emperor: "宋光宗", + Nianhao: "绍熙", + Dynasty: "宋", + }, + { + Year: 1174, + Emperor: "宋孝宗", + Nianhao: "淳熙", + Dynasty: "宋", + }, + { + Year: 1165, + Emperor: "宋孝宗", + Nianhao: "乾道", + Dynasty: "宋", + }, + { + Year: 1163, + Emperor: "宋孝宗", + Nianhao: "隆兴", + Dynasty: "宋", + }, + { + Year: 1131, + Emperor: "宋高宗", + Nianhao: "绍兴", + Dynasty: "宋", + }, + { + Year: 1127, + Emperor: "宋高宗", + OtherNianHaoStart: "建炎", + Dynasty: "宋", + }, + { + Year: 1126, + Emperor: "宋钦宗", + OtherNianHaoStart: "靖康", + Dynasty: "宋", + }, + { + Year: 1119, + Emperor: "宋徽宗", + OtherNianHaoStart: "宣和", + Dynasty: "宋", + }, + { + Year: 1118, + Emperor: "宋徽宗", + OtherNianHaoStart: "重和", + Dynasty: "宋", + }, + { + Year: 1111, + Emperor: "宋徽宗", + Nianhao: "政和", + Dynasty: "宋", + }, + { + Year: 1107, + Emperor: "宋徽宗", + Nianhao: "大观", + Dynasty: "宋", + }, + { + Year: 1102, + Emperor: "宋徽宗", + Nianhao: "崇宁", + Dynasty: "宋", + }, + { + Year: 1101, + Emperor: "宋徽宗", + Nianhao: "建中靖国", + Dynasty: "宋", + }, + { + Year: 1098, + Emperor: "宋哲宗", + OtherNianHaoStart: "元符", + Dynasty: "宋", + }, + { + Year: 1094, + Emperor: "宋哲宗", + OtherNianHaoStart: "绍圣", + Dynasty: "宋", + }, + { + Year: 1086, + Emperor: "宋哲宗", + Nianhao: "元佑", + Dynasty: "宋", + }, + { + Year: 1078, + Emperor: "宋神宗", + Nianhao: "元丰", + Dynasty: "宋", + }, + { + Year: 1068, + Emperor: "宋神宗", + Nianhao: "熙宁", + Dynasty: "宋", + }, + { + Year: 1064, + Emperor: "宋英宗", + Nianhao: "治平", + Dynasty: "宋", + }, + { + Year: 1056, + Emperor: "宋仁宗", + OtherNianHaoStart: "嘉佑", + Dynasty: "宋", + }, + { + Year: 1054, + Emperor: "宋仁宗", + OtherNianHaoStart: "至和", + Dynasty: "宋", + }, + { + Year: 1049, + Emperor: "宋仁宗", + Nianhao: "皇佑", + Dynasty: "宋", + }, + { + Year: 1041, + Emperor: "宋仁宗", + OtherNianHaoStart: "庆历", + Dynasty: "宋", + }, + { + Year: 1040, + Emperor: "宋仁宗", + OtherNianHaoStart: "康定", + Dynasty: "宋", + }, + { + Year: 1038, + Emperor: "宋仁宗", + OtherNianHaoStart: "宝元", + Dynasty: "宋", + }, + { + Year: 1034, + Emperor: "宋仁宗", + Nianhao: "景佑", + Dynasty: "宋", + }, + { + Year: 1032, + Emperor: "宋仁宗", + OtherNianHaoStart: "明道", + Dynasty: "宋", + }, + { + Year: 1023, + Emperor: "宋仁宗", + Nianhao: "天圣", + Dynasty: "宋", + }, + { + Year: 1022, + Emperor: "宋真宗", + Nianhao: "乾兴", + Dynasty: "宋", + }, + { + Year: 1017, + Emperor: "宋真宗", + Nianhao: "天禧", + Dynasty: "宋", + }, + { + Year: 1008, + Emperor: "宋真宗", + Nianhao: "大中祥符", + Dynasty: "宋", + }, + { + Year: 1004, + Emperor: "宋真宗", + Nianhao: "景德", + Dynasty: "宋", + }, + { + Year: 998, + Emperor: "宋真宗", + Nianhao: "咸平", + Dynasty: "宋", + }, + { + Year: 995, + Emperor: "宋太宗", + Nianhao: "至道", + Dynasty: "宋", + }, + { + Year: 990, + Emperor: "宋太宗", + Nianhao: "淳化", + Dynasty: "宋", + }, + { + Year: 988, + Emperor: "宋太宗", + Nianhao: "端拱", + Dynasty: "宋", + }, + { + Year: 984, + Emperor: "宋太宗", + OtherNianHaoStart: "雍熙", + Dynasty: "宋", + }, + { + Year: 976, + Emperor: "宋太宗", + OtherNianHaoStart: "太平兴国", + Dynasty: "宋", + }, + { + Year: 968, + Emperor: "宋太祖", + OtherNianHaoStart: "开宝", + Dynasty: "宋", + }, + { + Year: 963, + Emperor: "宋太祖", + OtherNianHaoStart: "乾德", + Dynasty: "宋", + }, + { + Year: 960, + Emperor: "宋太祖", + OtherNianHaoStart: "建隆", + Dynasty: "宋", + }, + { + Year: 954, + Emperor: "后周世宗", + OtherNianHaoStart: "显德", + Dynasty: "后周", + }, + { + Year: 951, + Emperor: "后周太祖", + Nianhao: "广顺", + Dynasty: "后周", + }, + { + Year: 948, + Emperor: "后汉隐帝", + OtherNianHaoStart: "乾佑", + Dynasty: "后汉", + }, + { + Year: 944, + Emperor: "后晋出帝", + OtherNianHaoStart: "开运", + Dynasty: "后晋", + }, + { + Year: 936, + Emperor: "后晋高祖", + OtherNianHaoStart: "天福", + Dynasty: "后晋", + }, + { + Year: 934, + Emperor: "后唐末帝", + OtherNianHaoStart: "清泰", + Dynasty: "后唐", + }, + { + Year: 930, + Emperor: "后唐明宗", + OtherNianHaoStart: "长兴", + Dynasty: "后唐", + }, + { + Year: 926, + Emperor: "后唐明宗", + OtherNianHaoStart: "天成", + Dynasty: "后唐", + }, + { + Year: 923, + Emperor: "后唐庄宗", + OtherNianHaoStart: "同光", + Dynasty: "后唐", + }, + { + Year: 921, + Emperor: "后梁末帝", + OtherNianHaoStart: "龙德", + Dynasty: "后梁", + }, + { + Year: 915, + Emperor: "后梁末帝", + OtherNianHaoStart: "贞明", + Dynasty: "后梁", + }, + { + Year: 911, + Emperor: "后梁太祖", + OtherNianHaoStart: "乾化", + Dynasty: "后梁", + }, + { + Year: 907, + Emperor: "后梁太祖", + OtherNianHaoStart: "开平", + Dynasty: "后梁", + }, + { + Year: 904, + Emperor: "唐哀帝", + Nianhao: "天佑", + Dynasty: "唐", + }, + } +} + +func mingQingEras() []Era { + return []Era{ + { + Year: 1949, + Emperor: "新中国", + Nianhao: "", + Dynasty: "新中国", + }, + { + Year: 1912, + Emperor: "", + Nianhao: "民国", + Dynasty: "中华民国", + }, + { + Year: 1909, + Emperor: "清宣统帝", + Nianhao: "宣统", + Dynasty: "清", + }, + { + Year: 1875, + Emperor: "清德宗", + Nianhao: "光绪", + Dynasty: "清", + }, + { + Year: 1862, + Emperor: "清穆宗", + Nianhao: "同治", + Dynasty: "清", + }, + { + Year: 1851, + Emperor: "清文宗", + Nianhao: "咸丰", + Dynasty: "清", + }, + { + Year: 1821, + Emperor: "清宣宗", + Nianhao: "道光", + Dynasty: "清", + }, + { + Year: 1796, + Emperor: "清仁宗", + Nianhao: "嘉庆", + Dynasty: "清", + }, + { + Year: 1736, + Emperor: "清高宗", + Nianhao: "乾隆", + Dynasty: "清", + }, + { + Year: 1723, + Emperor: "清世宗", + Nianhao: "雍正", + Dynasty: "清", + }, + { + Year: 1662, + Emperor: "清圣祖", + Nianhao: "康熙", + Dynasty: "清", + }, + { + Year: 1644, + Emperor: "清世祖", + Nianhao: "顺治", + Dynasty: "清", + }, + { + Year: 1644, + Emperor: "清世祖", + OtherNianHaoStart: "顺治", + Dynasty: "清", + }, + { + Year: 1628, + Emperor: "明思宗", + Nianhao: "崇祯", + Dynasty: "明", + }, + { + Year: 1621, + Emperor: "明熹宗", + Nianhao: "天启", + Dynasty: "明", + }, + { + Year: 1620, + Emperor: "明光宗", + OtherNianHaoStart: "泰昌", + Dynasty: "明", + }, + { + Year: 1573, + Emperor: "明神宗", + Nianhao: "万历", + Dynasty: "明", + }, + { + Year: 1567, + Emperor: "明穆宗", + Nianhao: "隆庆", + Dynasty: "明", + }, + { + Year: 1522, + Emperor: "明世宗", + Nianhao: "嘉靖", + Dynasty: "明", + }, + { + Year: 1506, + Emperor: "明武宗", + Nianhao: "正德", + Dynasty: "明", + }, + { + Year: 1488, + Emperor: "明孝宗", + Nianhao: "弘治", + Dynasty: "明", + }, + { + Year: 1465, + Emperor: "明宪宗", + Nianhao: "成化", + Dynasty: "明", + }, + { + Year: 1457, + Emperor: "明英宗", + Nianhao: "天顺", + Dynasty: "明", + }, + { + Year: 1450, + Emperor: "明代宗", + Nianhao: "景泰", + Dynasty: "明", + }, + { + Year: 1436, + Emperor: "明英宗", + Nianhao: "正统", + Dynasty: "明", + }, + { + Year: 1426, + Emperor: "明宣宗", + Nianhao: "宣德", + Dynasty: "明", + }, + { + Year: 1425, + Emperor: "明仁宗", + Nianhao: "洪熙", + Dynasty: "明", + }, + { + Year: 1403, + Emperor: "明成祖", + Nianhao: "永乐", + Dynasty: "明", + }, + { + Year: 1399, + Emperor: "明惠帝", + Nianhao: "建文", + Dynasty: "明", + }, + { + Year: 1368, + Emperor: "明太祖", + OtherNianHaoStart: "洪武", + Dynasty: "明", + }, + { + Year: 1341, + Emperor: "元顺帝", + Nianhao: "至正", + Dynasty: "元", + }, + } +} diff --git a/calendar/time.go b/calendar/time.go new file mode 100644 index 0000000..77a3288 --- /dev/null +++ b/calendar/time.go @@ -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 +} diff --git a/moon/moon.go b/moon/moon.go index 41b1514..f7f2f0b 100644 --- a/moon/moon.go +++ b/moon/moon.go @@ -1,6 +1,7 @@ package moon import ( + "b612.me/astro/tools" "errors" "math" "time" @@ -201,7 +202,7 @@ func SetTime(date time.Time, lon, lat, height float64, aero bool) (time.Time, er if aero { aeroFloat = 1 } - downJde := basic.GetMoonDownTime(jde, lon, lat, timezone, aeroFloat, height) + downJde := basic.GetMoonSetTime(jde, lon, lat, timezone, aeroFloat, height) if downJde == -3 { 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 } +// 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 月相 // 返回Date对应UTC世界时的月相大小 func Phase(date time.Time) float64 { diff --git a/sun/sun.go b/sun/sun.go index 7e248c2..b637b6b 100644 --- a/sun/sun.go +++ b/sun/sun.go @@ -2,6 +2,7 @@ package sun import ( "errors" + "math" "time" "b612.me/astro/basic" @@ -284,3 +285,27 @@ func EarthDistance(date time.Time) float64 { jde = basic.TD2UT(jde, true) 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))) +}