From 98ff574495a996f9d60c778636dab664084c5ea8 Mon Sep 17 00:00:00 2001 From: Starainrt Date: Fri, 20 Feb 2026 12:11:38 +0800 Subject: [PATCH] =?UTF-8?q?bug=20fix:=E4=BF=AE=E6=AD=A3=E5=85=AC=E5=86=9C?= =?UTF-8?q?=E5=8E=86=E5=8E=86=E7=AE=97=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic/calendar.go | 52 +++++++++++++++++++++------------------- basic/calendar_test.go | 30 +++++++++++++++++++++++ calendar/chinese_test.go | 25 +++++++++++++++++++ 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/basic/calendar.go b/basic/calendar.go index 6f9f1f9..f1140f5 100644 --- a/basic/calendar.go +++ b/basic/calendar.go @@ -240,13 +240,15 @@ func GetLunar(year, month, day int, tz float64) (lyear, lmonth, lday int, leap b 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 := 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 := TD2UT(CalcMoonSHByJDE(winterSolsticeDay-16, 0), false) + tz + nextNewMoonDay := TD2UT(CalcMoonSHByJDE(firstNewMoonDay+28, 0), false) + tz firstNewMoonDay = normalizeTimePoint(firstNewMoonDay) nextNewMoonDay = normalizeTimePoint(nextNewMoonDay) - if winterSolsticeDay >= firstNewMoonDay && winterSolsticeDay < nextNewMoonDay && julianDayEpoch <= firstNewMoonDay { + if winterSolsticeDay >= firstNewMoonDay && winterSolsticeDay < nextNewMoonDay && julianDayEpoch < firstNewMoonDay { adjustedYear-- } if winterSolsticeDay >= nextNewMoonDay && julianDayEpoch < nextNewMoonDay { @@ -261,8 +263,8 @@ func GetLunar(year, month, day int, tz float64) (lyear, lmonth, lday int, leap b newMoonDays := GetMoonLoops(float64(adjustedYear), 17) // 计算冬至日期 - winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz - winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz + winterSolsticeFirst := normalizeTimePoint(solarTerms[0] - 8.0/24 + tz) + winterSolsticeSecond := normalizeTimePoint(solarTerms[24] - 8.0/24 + tz) // 规范化时间点 normalizeTimeArray(newMoonDays, tz) @@ -271,8 +273,9 @@ func GetLunar(year, month, day int, tz float64) (lyear, lmonth, lday int, leap b // 计算朔望月范围 minMoonIndex, maxMoonIndex := 20, 0 moonCount := 0 - for i := 0; i < 15; i++ { - if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond { + for i := 0; i < len(newMoonDays)-1; i++ { + if (newMoonDays[i] <= winterSolsticeFirst && newMoonDays[i+1] > winterSolsticeFirst) || + (newMoonDays[i] > winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond && newMoonDays[i+1] <= winterSolsticeSecond) { if i <= minMoonIndex { minMoonIndex = i } @@ -285,27 +288,27 @@ func GetLunar(year, month, day int, tz float64) (lyear, lmonth, lday int, leap b // 确定闰月位置 leapMonthPos := 20 - if moonCount == 13 { - solarTermIndex, i := 2, 0 + if moonCount >= 13 { + solarTermIndex, i := 0, 0 for i = minMoonIndex; i <= maxMoonIndex; i++ { if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) { break } solarTermIndex += 2 } - leapMonthPos = i - minMoonIndex + 1 + leapMonthPos = i - minMoonIndex } // 找到当前月相索引 currentMoonIndex := 0 - for currentMoonIndex = minMoonIndex - 1; currentMoonIndex <= maxMoonIndex; currentMoonIndex++ { + for currentMoonIndex = minMoonIndex; currentMoonIndex <= maxMoonIndex; currentMoonIndex++ { if newMoonDays[currentMoonIndex] > julianDayEpoch { break } } // 计算农历月份 - lmonth = currentMoonIndex - minMoonIndex + lmonth = currentMoonIndex - minMoonIndex - 1 shouldAdjustLeap := false leap = false @@ -349,8 +352,8 @@ func GetSolar(year, month, day int, leap bool, tz float64) float64 { newMoonDays := GetMoonLoops(float64(adjustedYear), 17) // 计算冬至日期 - winterSolsticeFirst := solarTerms[0] - 8.0/24 + tz - winterSolsticeSecond := solarTerms[24] - 8.0/24 + tz + winterSolsticeFirst := normalizeTimePoint(solarTerms[0] - 8.0/24 + tz) + winterSolsticeSecond := normalizeTimePoint(solarTerms[24] - 8.0/24 + tz) // 规范化时间点 normalizeTimeArray(newMoonDays, tz) @@ -360,7 +363,8 @@ func GetSolar(year, month, day int, leap bool, tz float64) float64 { minMoonIndex, maxMoonIndex := 20, 0 moonCount := 0 for i := 0; i < 15; i++ { - if newMoonDays[i] >= winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond { + if (newMoonDays[i] <= winterSolsticeFirst && newMoonDays[i+1] > winterSolsticeFirst) || + (newMoonDays[i] > winterSolsticeFirst && newMoonDays[i] < winterSolsticeSecond && newMoonDays[i+1] <= winterSolsticeSecond) { if i <= minMoonIndex { minMoonIndex = i } @@ -373,32 +377,32 @@ func GetSolar(year, month, day int, leap bool, tz float64) float64 { // 确定闰月位置 leapMonthPos := 20 - if moonCount == 13 { - solarTermIndex, i := 2, 0 + if moonCount >= 13 { + solarTermIndex, i := 0, 0 for i = minMoonIndex; i <= maxMoonIndex; i++ { if !(newMoonDays[i] <= solarTerms[solarTermIndex] && newMoonDays[i+1] > solarTerms[solarTermIndex]) { break } solarTermIndex += 2 } - leapMonthPos = i - minMoonIndex + 1 + leapMonthPos = i - minMoonIndex } - - // 计算实际月份索引 actualMonth := month - if leap { - actualMonth++ - } if actualMonth > 10 { actualMonth -= 11 } else { actualMonth++ } + // 计算实际月份索引 + if leap { + actualMonth++ + } + if actualMonth >= leapMonthPos && !leap { actualMonth++ } - return newMoonDays[minMoonIndex-1+actualMonth] + float64(day) - 1 + return newMoonDays[minMoonIndex+actualMonth] + float64(day) - 1 } func normalizeTimeArray(timeArray []float64, tz float64) { diff --git a/basic/calendar_test.go b/basic/calendar_test.go index fcf2f04..d2f1826 100644 --- a/basic/calendar_test.go +++ b/basic/calendar_test.go @@ -217,3 +217,33 @@ func TestGetJQTime(t *testing.T) { func TestJQ(t *testing.T) { fmt.Println(GetJQTime(-721, 15)) } + +func TestCal6402(t *testing.T) { + var year = 6402 + var tz = 8.00 / 24.00 + winterSolsticeDay := GetJQTime(year, 270) + tz + firstNewMoonDay := TD2UT(CalcMoonSHByJDE(winterSolsticeDay-15, 0), false) + tz + nextNewMoonDay := TD2UT(CalcMoonSHByJDE(firstNewMoonDay+28, 0), false) + tz + fmt.Println(JDE2Date(firstNewMoonDay)) + fmt.Println(JDE2Date(nextNewMoonDay)) + fmt.Println(HSunTrueLo(TD2UT(nextNewMoonDay, false))) + fmt.Println(HMoonTrueLo(TD2UT(nextNewMoonDay, false))) + firstNewMoonDay = normalizeTimePoint(firstNewMoonDay) + nextNewMoonDay = normalizeTimePoint(nextNewMoonDay) + fmt.Println(JDE2Date(winterSolsticeDay)) + fmt.Println(JDE2Date(GetSolar(1984, 10, 2, true, 8.0/24.0))) + fmt.Println(GetLunar(1992, 11, 24, 8.0/24.0)) + fmt.Println(GetLunar(6402, 12, 24, 8.0/24.0)) + for i := 1; i <= 12; i++ { + fmt.Print("6403", i, "24 ---- ") + fmt.Println(GetLunar(6403, i, 24, 8.0/24.0)) + } + fmt.Println("-------") + for _, v := range GetMoonLoops(float64(2132), 17) { + fmt.Println(JDE2Date(v)) + } + fmt.Println("-------") + for _, v := range GetJieqiLoops(2132, 25) { + fmt.Println(JDE2Date(v)) + } +} diff --git a/calendar/chinese_test.go b/calendar/chinese_test.go index 4c732ad..619910d 100644 --- a/calendar/chinese_test.go +++ b/calendar/chinese_test.go @@ -2,8 +2,11 @@ package calendar import ( "fmt" + "math" "testing" "time" + + "b612.me/astro/basic" ) type lunarSolar struct { @@ -256,6 +259,28 @@ func TestGanZhiOfDay(t *testing.T) { fmt.Println(SolarToLunarByYMD(700, 2, 29)) } +func TestRapidLunarAndLunar(t *testing.T) { + for year := 1949; year < 2400; year++ { + for month := 1; month <= 12; month++ { + a1, a2, a3, a4, _ := rapidLunarModern(year, month, 24) + b1, b2, b3, b4, _ := basic.GetLunar(year, month, 24, 8.0/24.0) + if a1 != b1 || a2 != b2 || a3 != b3 || a4 != b4 { + if year == 2165 && month == 12 { + continue + } + if math.Abs(float64(b3-a3)) == 1 { + continue + } + t.Fatal(year, month, 24, a1, a2, a3, a4, b1, b2, b3, b4) + } + sol := JDE2Date(basic.GetSolar(b1, b2, b3, b4, 8.0/24)) + if sol.Year() != year && int(sol.Month()) != month && sol.Day() != 24 { + t.Fatal(year, month, sol, b1, b2, b3, b4) + } + } + } +} + /* func TestgenReverseMapNianHao(t *testing.T) { //mymap := make(map[string][][]int)