diff --git a/calendar/chinese.go b/calendar/chinese.go index f9a8839..8731c99 100644 --- a/calendar/chinese.go +++ b/calendar/chinese.go @@ -78,8 +78,19 @@ func SolarToLunar(date time.Time) (Time, error) { return innerSolarToLunar(date) } +// SolarToLunarByYMD 公历转农历 +// 传入 公历年月日 +// 返回 包含农历信息的Time结构体 +// 支持年份:[-103,3000] +// [-103,1912] 按照古代历法提供的农历信息 +// (1912,3000]按现行农历GB/T 33661-2017算法计算 +func SolarToLunarByYMD(year, month, day int) (Time, error) { + return innerSolarToLunarByYMD(year, month, day) +} + func innerSolarToLunar(date time.Time) (Time, error) { - if date.Year() < -103 || date.Year() > 3000 { + date = date.In(getCst()) + if date.Year() < -103 || date.Year() > 9999 { return Time{}, fmt.Errorf("日期超出范围") } if date.Year() <= 1912 { @@ -96,6 +107,30 @@ func innerSolarToLunar(date time.Time) (Time, error) { return transformModenLunar2Time(date, y, m, d, l, desc), nil } +func innerSolarToLunarByYMD(year, month, day int) (Time, error) { + if year < -103 || year > 9999 { + return Time{}, fmt.Errorf("日期超出范围") + } + if month < 1 || month > 12 { + return Time{}, fmt.Errorf("月份超出范围") + } + if day < 1 || day > 31 { + return Time{}, fmt.Errorf("日期超出范围") + } + if year <= 1912 { + return innerSolarToLunarHanQingByYMD(year, month, day, time.Time{}), nil + } + if year < 2400 { + y, m, d, l, desc := rapidLunarModern(year, month, day) + if desc == "无法获取农历信息" { + return Time{}, fmt.Errorf("无法获取农历信息") + } + return transformModenLunar2Time(time.Date(year, time.Month(month), day, 0, 0, 0, 0, getCst()), y, m, d, l, desc), nil + } + y, m, d, l, desc := basic.GetLunar(year, month, day, 8.0/24.0) + return transformModenLunar2Time(time.Date(year, time.Month(month), day, 0, 0, 0, 0, getCst()), y, m, d, l, desc), nil +} + func transformModenLunar2Time(date time.Time, year, month, day int, leap bool, desc string) Time { return Time{ solarTime: date, @@ -141,13 +176,24 @@ func LunarToSolar(desc string) ([]Time, error) { } // LunarToSolarSingle 农历转公历 +// Deprecated: 推荐使用LunarToSolarByYMD // 传入 农历年月日,是否闰月 // 传出 包含公里农历信息的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 LunarToSolarByYMD(year, month, day, leap) +} + +// LunarToSolarByYMD 农历转公历 +// 传入 农历年月日,是否闰月 +// 传出 包含公里农历信息的Time结构体 +// 支持年份:[-103,3000] +// [-103,1912] 按照古代历法提供的农历信息,注意,这里农历月份代表的是以当时的历法推定的农历月与正月的距离,正月为1,二月为2,依次类推,闰月显示所闰月 +// (1912,3000]按现行农历GB/T 33661-2017算法计算 +func LunarToSolarByYMD(year, month, day int, leap bool) (Time, error) { + if year < -103 || year > 9999 { return Time{}, fmt.Errorf("年份超出范围") } if year <= 1912 { diff --git a/calendar/chineseHantoQing.go b/calendar/chineseHantoQing.go index d984c72..3c94a37 100644 --- a/calendar/chineseHantoQing.go +++ b/calendar/chineseHantoQing.go @@ -48,6 +48,9 @@ recalc: //儒略历修正 if springDate.Year()%100 == 0 && springDate.Year()%400 != 0 && springDate.Year() < 1582 && (target.Month() >= 3 || (target.Year() > springDate.Year())) { diffDay++ + if target.Month() == 3 && target.Day() == 1 && month == 2 && day == 29 { + diffDay-- + } } //儒略历转格里高历修正 if calcYear == 1582 && ((month == 10 && day >= 15) || month > 10) { @@ -268,10 +271,21 @@ func formatLunarDateString(lunarMonth, lunarDay int, isLeap bool, diff int) stri } func innerSolarToLunarHanQing(date time.Time) Time { - year := date.Year() - month := int(date.Month()) - day := date.Day() + return innerSolarToLunarHanQingByYMD(0, 0, 0, date) +} + +func innerSolarToLunarHanQingByYMD(year, month, day int, hmi time.Time) Time { + loc := getCst() + if !hmi.IsZero() { + loc = hmi.Location() + } + if !hmi.IsZero() && year == 0 && month == 0 && day == 0 { + year = hmi.Year() + month = int(hmi.Month()) + day = hmi.Day() + } yeardiff := yearDiff(year, month, day) + date := time.Date(year, time.Month(month), day, hmi.Hour(), hmi.Minute(), hmi.Second(), hmi.Nanosecond(), loc) lyear, lmonth, ganzhiMonth, lday, isLeap, ldesc := rapidLunarHan2Qing(year, month, day, yeardiff, nil) var eras []EraDesc if lyear >= -103 && lyear <= 220 { diff --git a/calendar/chinese_test.go b/calendar/chinese_test.go index 2a34580..4c732ad 100644 --- a/calendar/chinese_test.go +++ b/calendar/chinese_test.go @@ -111,7 +111,7 @@ func Test_ChineseCalendarModern2(t *testing.T) { t.Fatal(v, lunar.year, lunar.month, lunar.day, lunar.leap) } - date, err := LunarToSolarSingle(v.Lyear, v.Lmonth, v.Lday, v.Leap) + date, err := LunarToSolarByYMD(v.Lyear, v.Lmonth, v.Lday, v.Leap) if err != nil { t.Fatal(err) } @@ -253,6 +253,7 @@ func TestGanZhiOfDay(t *testing.T) { fmt.Println(v.solarTime) fmt.Println(v.LunarDescWithDynastyAndEmperor()) } + fmt.Println(SolarToLunarByYMD(700, 2, 29)) } /*