diff --git a/calendar/chinese.go b/calendar/chinese.go index 6ded63a..6135e67 100644 --- a/calendar/chinese.go +++ b/calendar/chinese.go @@ -518,6 +518,21 @@ func parseChineseDate(dateStr string) (LunarTime, error) { var result LunarTime var err error result.desc = dateStr + if strings.HasPrefix(dateStr, "前") { + originDateStr := dateStr + dateStr = strings.TrimPrefix(dateStr, "前") + re := regexp.MustCompile(`^([-一二三四五六七八九十零〇\d]+?)年`) + matches := re.FindStringSubmatch(dateStr) + if len(matches) == 2 { + year, err := parseDirectYear(matches[1]) + if err != nil { + return result, err + } + dateStr = "-" + strconv.Itoa(year-1) + strings.TrimPrefix(dateStr, matches[1]) + } else { + dateStr = originDateStr + } + } dateStr = "公元" + dateStr // 正则表达式匹配日期格式 re := regexp.MustCompile(`^([\p{Han}]+?)([-负負一二三四五六七八九十零〇\d]*?元?)年([\p{Han}\d]+?)月([\p{Han}\d]+?)日?$`) @@ -614,6 +629,21 @@ func parseChineseDate(dateStr string) (LunarTime, error) { return result, nil } +func parseDirectYear(yearStr string) (int, error) { + if m, _ := regexp.MatchString("\\d+", yearStr); m { + year, err := strconv.Atoi(yearStr) + if err != nil { + return 0, fmt.Errorf("无效的年份: %s", yearStr) + } + return year, nil + } + year := transfer(yearStr, true) + if year == 0 { + return 0, fmt.Errorf("无效的年份: %s", yearStr) + } + return year, nil +} + // convertChineseNumber 将中文数字转换为阿拉伯数字 func convertChineseNumber(chineseNum string) (int, error) { if num, ok := chineseNumbers[chineseNum]; ok { diff --git a/calendar/chineseAncient.go b/calendar/chineseAncient.go index 953c810..520af1c 100644 --- a/calendar/chineseAncient.go +++ b/calendar/chineseAncient.go @@ -101,6 +101,11 @@ func LunarToSolarWithCalendar(desc string, system AncientCalendarSystem) ([]Time return nil, err } if date.year == 0 || date.comment != "" { + if date.comment != "" { + if result, known, err := lunarToSolarAncientEra(date, system); known { + return result, err + } + } return nil, fmt.Errorf("显式古历暂不支持年号日期") } if date.houMonth && system != AncientCalendarQinHan && system != AncientCalendarZhuanxu { @@ -616,6 +621,7 @@ func ancientTime(date time.Time, month ancientMonth) Time { desc: formatAncientLunarDateString(month.month, month.day, month.leap, month.system), calendarSystem: month.system, calendarName: month.name, + eras: ancientErasForLunarYear(month.lunarYear, month.system), }, }, } @@ -625,6 +631,9 @@ func tagCalendar(date Time, system AncientCalendarSystem, name string) Time { for i := range date.lunars { date.lunars[i].calendarSystem = system date.lunars[i].calendarName = name + if len(date.lunars[i].eras) == 0 { + date.lunars[i].eras = ancientErasForLunarYear(date.lunars[i].year, system) + } } return date } diff --git a/calendar/chineseAncientEra.go b/calendar/chineseAncientEra.go new file mode 100644 index 0000000..13b7737 --- /dev/null +++ b/calendar/chineseAncientEra.go @@ -0,0 +1,212 @@ +package calendar + +import "fmt" + +type ancientEraSource struct { + system AncientCalendarSystem + min int + max int + eras []Era +} + +var zhouAncientEras = []Era{ + {Year: -313, Emperor: "周赧王", Nianhao: "周赧王", Dynasty: "周"}, + {Year: -319, Emperor: "周慎靓王", Nianhao: "周慎靓王", Dynasty: "周"}, + {Year: -367, Emperor: "周显王", Nianhao: "周显王", Dynasty: "周"}, + {Year: -374, Emperor: "周烈王", Nianhao: "周烈王", Dynasty: "周"}, + {Year: -400, Emperor: "周安王", Nianhao: "周安王", Dynasty: "周"}, + {Year: -424, Emperor: "周威烈王", Nianhao: "周威烈王", Dynasty: "周"}, + {Year: -439, Emperor: "周考王", Nianhao: "周考王", Dynasty: "周"}, + {Year: -467, Emperor: "周贞定王", Nianhao: "周贞定王", Dynasty: "周"}, + {Year: -475, Emperor: "周元王", Nianhao: "周元王", Dynasty: "周"}, + {Year: -518, Emperor: "周敬王", Nianhao: "周敬王", Dynasty: "周"}, + {Year: -543, Emperor: "周景王", Nianhao: "周景王", Dynasty: "周"}, + {Year: -570, Emperor: "周灵王", Nianhao: "周灵王", Dynasty: "周"}, + {Year: -584, Emperor: "周简王", Nianhao: "周简王", Dynasty: "周"}, + {Year: -605, Emperor: "周定王", Nianhao: "周定王", Dynasty: "周"}, + {Year: -611, Emperor: "周匡王", Nianhao: "周匡王", Dynasty: "周"}, + {Year: -617, Emperor: "周顷王", Nianhao: "周顷王", Dynasty: "周"}, + {Year: -650, Emperor: "周襄王", Nianhao: "周襄王", Dynasty: "周"}, + {Year: -675, Emperor: "周惠王", Nianhao: "周惠王", Dynasty: "周"}, + {Year: -680, Emperor: "周僖王", Nianhao: "周僖王", Dynasty: "周"}, + {Year: -695, Emperor: "周庄王", Nianhao: "周庄王", Dynasty: "周"}, + {Year: -718, Emperor: "周桓王", Nianhao: "周桓王", Dynasty: "周"}, + {Year: -771, Emperor: "周平王", Nianhao: "周平王", Dynasty: "周"}, +} + +var luAncientEras = []Era{ + {Year: -271, Emperor: "鲁顷公", Nianhao: "鲁顷公", Dynasty: "鲁"}, + {Year: -294, Emperor: "鲁文公", Nianhao: "鲁文公", Dynasty: "鲁"}, + {Year: -313, Emperor: "鲁平公", Nianhao: "鲁平公", Dynasty: "鲁"}, + {Year: -342, Emperor: "鲁景公", Nianhao: "鲁景公", Dynasty: "鲁"}, + {Year: -351, Emperor: "鲁康公", Nianhao: "鲁康公", Dynasty: "鲁"}, + {Year: -375, Emperor: "鲁共公", Nianhao: "鲁共公", Dynasty: "鲁"}, + {Year: -406, Emperor: "鲁穆公", Nianhao: "鲁穆公", Dynasty: "鲁"}, + {Year: -427, Emperor: "鲁元公", Nianhao: "鲁元公", Dynasty: "鲁"}, + {Year: -465, Emperor: "鲁悼公", Nianhao: "鲁悼公", Dynasty: "鲁"}, + {Year: -493, Emperor: "鲁哀公", Nianhao: "鲁哀公", Dynasty: "鲁"}, + {Year: -508, Emperor: "鲁定公", Nianhao: "鲁定公", Dynasty: "鲁"}, + {Year: -540, Emperor: "鲁昭公", Nianhao: "鲁昭公", Dynasty: "鲁"}, + {Year: -571, Emperor: "鲁襄公", Nianhao: "鲁襄公", Dynasty: "鲁"}, + {Year: -589, Emperor: "鲁成公", Nianhao: "鲁成公", Dynasty: "鲁"}, + {Year: -607, Emperor: "鲁宣公", Nianhao: "鲁宣公", Dynasty: "鲁"}, + {Year: -625, Emperor: "鲁文公", Nianhao: "鲁文公", Dynasty: "鲁"}, + {Year: -658, Emperor: "鲁僖公", Nianhao: "鲁僖公", Dynasty: "鲁"}, + {Year: -660, Emperor: "鲁闵公", Nianhao: "鲁闵公", Dynasty: "鲁"}, + {Year: -692, Emperor: "鲁庄公", Nianhao: "鲁庄公", Dynasty: "鲁"}, + {Year: -710, Emperor: "鲁桓公", Nianhao: "鲁桓公", Dynasty: "鲁"}, + {Year: -721, Emperor: "鲁隐公", Nianhao: "鲁隐公", Dynasty: "鲁"}, + {Year: -767, Emperor: "鲁惠公", Nianhao: "鲁惠公", Dynasty: "鲁"}, +} + +var qinWarringAncientEras = []Era{ + {Year: -245, Emperor: "秦王政", Nianhao: "秦王政", Dynasty: "秦"}, + {Year: -248, Emperor: "秦庄襄王", Nianhao: "秦庄襄王", Dynasty: "秦"}, + {Year: -249, Emperor: "秦孝文王", Nianhao: "秦孝文王", Dynasty: "秦"}, + {Year: -305, Emperor: "秦昭襄王", Nianhao: "秦昭襄王", Dynasty: "秦"}, +} + +var qinHanAncientEras = []Era{ + {Year: -109, Emperor: "汉武帝", Nianhao: "元封", Dynasty: "西汉"}, + {Year: -115, Emperor: "汉武帝", Nianhao: "元鼎", Dynasty: "西汉"}, + {Year: -121, Emperor: "汉武帝", Nianhao: "元狩", Dynasty: "西汉"}, + {Year: -127, Emperor: "汉武帝", Nianhao: "元朔", Dynasty: "西汉"}, + {Year: -133, Emperor: "汉武帝", Nianhao: "元光", Dynasty: "西汉"}, + {Year: -139, Emperor: "汉武帝", Nianhao: "建元", Dynasty: "西汉"}, + {Year: -142, Emperor: "汉景帝", Nianhao: "后元", Dynasty: "西汉"}, + {Year: -148, Emperor: "汉景帝", Nianhao: "中元", Dynasty: "西汉"}, + {Year: -155, Emperor: "汉景帝", Nianhao: "前元", Dynasty: "西汉"}, + {Year: -162, Emperor: "汉文帝", Nianhao: "后元", Dynasty: "西汉"}, + {Year: -178, Emperor: "汉文帝", Nianhao: "前元", Dynasty: "西汉"}, + {Year: -186, Emperor: "汉高后", Nianhao: "汉高后", Dynasty: "西汉"}, + {Year: -193, Emperor: "汉惠帝", Nianhao: "汉惠帝", Dynasty: "西汉"}, + {Year: -205, Emperor: "汉高祖", Nianhao: "汉高祖", Dynasty: "西汉"}, + {Year: -208, Emperor: "秦二世", Nianhao: "秦二世", Dynasty: "秦"}, + {Year: -245, Emperor: "秦始皇", Nianhao: "秦始皇", Dynasty: "秦"}, +} + +func ancientErasForLunarYear(year int, system AncientCalendarSystem) []EraDesc { + switch system { + case AncientCalendarQinHan: + return ancientErasInRange(year, qinHanAncientEras, qinHanMinYear, qinHanMaxYear) + case AncientCalendarChunqiu, AncientCalendarLu: + return ancientErasInRange(year, luAncientEras, ancientBoundaryMinYear, -248) + case AncientCalendarZhuanxu: + if eras := ancientErasInRange(year, qinWarringAncientEras, -305, ancientBoundaryMaxYear); len(eras) > 0 { + return eras + } + return ancientErasInRange(year, zhouAncientEras, ancientBoundaryMinYear, -255) + case AncientCalendarZhou, AncientCalendarHuangdi, AncientCalendarYin, AncientCalendarXia1, AncientCalendarXia2: + return ancientErasInRange(year, zhouAncientEras, ancientBoundaryMinYear, -255) + default: + return nil + } +} + +func ancientErasInRange(year int, eras []Era, min, max int) []EraDesc { + if len(eras) == 0 || year < min || year > max { + return nil + } + return innerEras(year, func() []Era { return eras }) +} + +func ancientEraSourcesForSystem(system AncientCalendarSystem) []ancientEraSource { + switch system { + case AncientCalendarDefault: + return []ancientEraSource{ + {system: AncientCalendarQinHan, min: qinHanMinYear, max: qinHanMaxYear, eras: qinHanAncientEras}, + {system: AncientCalendarChunqiu, min: ancientBoundaryMinYear, max: -480, eras: luAncientEras}, + {system: AncientCalendarZhou, min: -479, max: -255, eras: zhouAncientEras}, + } + case AncientCalendarQinHan: + return []ancientEraSource{{system: system, min: qinHanMinYear, max: qinHanMaxYear, eras: qinHanAncientEras}} + case AncientCalendarChunqiu, AncientCalendarLu: + return []ancientEraSource{{system: system, min: ancientBoundaryMinYear, max: -248, eras: luAncientEras}} + case AncientCalendarZhuanxu: + return []ancientEraSource{ + {system: system, min: -305, max: ancientBoundaryMaxYear, eras: qinWarringAncientEras}, + {system: system, min: ancientBoundaryMinYear, max: -255, eras: zhouAncientEras}, + } + case AncientCalendarZhou, AncientCalendarHuangdi, AncientCalendarYin, AncientCalendarXia1, AncientCalendarXia2: + return []ancientEraSource{{system: system, min: ancientBoundaryMinYear, max: -255, eras: zhouAncientEras}} + default: + return nil + } +} + +func lunarToSolarAncientEra(data LunarTime, system AncientCalendarSystem) ([]Time, bool, error) { + sources := ancientEraSourcesForSystem(system) + if len(sources) == 0 { + return nil, false, nil + } + known := false + var results []Time + for _, source := range sources { + years, matched := ancientEraYears(source, data.comment, data.year) + if !matched { + continue + } + known = true + for _, year := range years { + times, err := lunarToSolarAncientEraYear(data, year, source.system) + if err == nil { + results = append(results, times...) + } + } + } + if !known { + return nil, false, nil + } + if len(results) == 0 { + return nil, true, fmt.Errorf("未找到对应日期") + } + return results, true, nil +} + +func ancientEraYears(source ancientEraSource, nianhao string, ordinal int) ([]int, bool) { + var years []int + matched := false + for idx, era := range source.eras { + if era.Nianhao != nianhao && era.Emperor != nianhao { + continue + } + matched = true + end := source.max + if idx > 0 && source.eras[idx-1].Year-1 < end { + end = source.eras[idx-1].Year - 1 + } + year := era.Year + ordinal - 1 - era.Offset + if year >= source.min && year >= era.Year && year <= end { + years = append(years, year) + } + } + return years, matched +} + +func lunarToSolarAncientEraYear(data LunarTime, year int, system AncientCalendarSystem) ([]Time, error) { + if data.houMonth && system != AncientCalendarQinHan && system != AncientCalendarZhuanxu { + return nil, fmt.Errorf("未找到对应日期") + } + if data.ganzhiMonth == "" || data.day != 0 { + result, err := LunarToSolarByYMDWithCalendar(year, data.month, data.day, data.leap, system) + if err != nil { + return nil, err + } + return []Time{result}, nil + } + + var results []Time + for day := 1; day <= 30; day++ { + result, err := LunarToSolarByYMDWithCalendar(year, data.month, day, data.leap, system) + if err != nil { + continue + } + if GanZhiOfDay(result.Solar()) == data.ganzhiMonth { + results = append(results, result) + } + } + if len(results) == 0 { + return nil, fmt.Errorf("未找到对应日期") + } + return results, nil +} diff --git a/calendar/chineseHantoQing.go b/calendar/chineseHantoQing.go index d005c0a..bcea599 100644 --- a/calendar/chineseHantoQing.go +++ b/calendar/chineseHantoQing.go @@ -359,6 +359,16 @@ func innerParseLunar(lunar string) ([]time.Time, error) { return []time.Time{}, err } if date.houMonth && date.comment != "" { + if data, known, err := lunarToSolarAncientEra(date, AncientCalendarDefault); known { + if err != nil { + return nil, err + } + var dates []time.Time + for _, v := range data { + dates = append(dates, v.Solar()) + } + return dates, nil + } return nil, fmt.Errorf("未找到对应日期") } if date.year != 0 && date.comment == "" { @@ -427,6 +437,16 @@ func innerParseLunar(lunar string) ([]time.Time, error) { if tmp, err := innerLunar2SolarHanQing(date, nanMingEraMap, nanMingCals); err == nil { data = append(data, tmp...) } + if date.comment != "" { + if ancientData, known, ancientErr := lunarToSolarAncientEra(date, AncientCalendarDefault); known { + if ancientErr != nil && len(data) == 0 { + return nil, ancientErr + } + for _, v := range ancientData { + data = append(data, v.Solar()) + } + } + } if len(data) == 0 { if err == ERR_NIANHAO_NOT_FOUND { return nil, err diff --git a/calendar/chineseQinHan.go b/calendar/chineseQinHan.go index 3db4d62..a70af8f 100644 --- a/calendar/chineseQinHan.go +++ b/calendar/chineseQinHan.go @@ -74,6 +74,7 @@ func qinHanTime(date time.Time, month qinHanMonth) Time { day: month.day, leap: month.leap, desc: formatQinHanLunarDateString(month.month, month.day, month.leap), + eras: ancientErasForLunarYear(month.lunarYear, AncientCalendarQinHan), }, }, } diff --git a/calendar/chinese_test.go b/calendar/chinese_test.go index 13a0dd2..234db33 100644 --- a/calendar/chinese_test.go +++ b/calendar/chinese_test.go @@ -509,10 +509,14 @@ func Test_ChineseCalendarAncientNegativeYearDescRoundtrip(t *testing.T) { t.Fatal(err) } descs := res.LunarDesc() - if len(descs) != 1 || descs[0] != "负二五零年正月初一" { + if len(descs) != 1 || descs[0] != "前二五一年正月初一" { t.Fatalf("unexpected descs: %v", descs) } - for _, desc := range []string{descs[0], "負二五零年正月初一"} { + infos := res.LunarInfo() + if len(infos) != 1 || infos[0].LunarYearChn != "前二五一" || infos[0].EraDesc != "前二五一年" { + t.Fatalf("unexpected lunar info fallback: %#v", infos) + } + for _, desc := range []string{descs[0], "负二五零年正月初一", "負二五零年正月初一"} { results, err := LunarToSolar(desc) if err != nil { t.Fatal(desc, err) @@ -531,6 +535,80 @@ func Test_ChineseCalendarAncientNegativeYearDescRoundtrip(t *testing.T) { } } +func Test_ChineseCalendarAncientEra(t *testing.T) { + testData := []struct { + name string + system AncientCalendarSystem + lyear int + lmonth int + lday int + leap bool + want string + dynasty string + emperor string + nianhao string + eraYear int + }{ + {name: "qin er shi third year", system: AncientCalendarQinHan, lyear: -206, lmonth: 10, lday: 1, want: "秦二世三年十月初一", dynasty: "秦", emperor: "秦二世", nianhao: "秦二世", eraYear: 3}, + {name: "han gaozu first year", system: AncientCalendarQinHan, lyear: -205, lmonth: 10, lday: 1, want: "汉高祖元年十月初一", dynasty: "西汉", emperor: "汉高祖", nianhao: "汉高祖", eraYear: 1}, + {name: "han jingdi zhongyuan first year", system: AncientCalendarQinHan, lyear: -148, lmonth: 1, lday: 1, want: "中元元年正月初一", dynasty: "西汉", emperor: "汉景帝", nianhao: "中元", eraYear: 1}, + {name: "yuanfeng sixth leap ninth", system: AncientCalendarQinHan, lyear: -104, lmonth: 9, lday: 19, leap: true, want: "元封六年后九月十九", dynasty: "西汉", emperor: "汉武帝", nianhao: "元封", eraYear: 6}, + {name: "zhou an wang", system: AncientCalendarZhou, lyear: -400, lmonth: 1, lday: 1, want: "周安王元年正月初一", dynasty: "周", emperor: "周安王", nianhao: "周安王", eraYear: 1}, + {name: "lu ding gong", system: AncientCalendarChunqiu, lyear: -500, lmonth: 1, lday: 1, want: "鲁定公九年正月初一", dynasty: "鲁", emperor: "鲁定公", nianhao: "鲁定公", eraYear: 9}, + } + for _, tc := range testData { + t.Run(tc.name, func(t *testing.T) { + result, err := LunarToSolarByYMDWithCalendar(tc.lyear, tc.lmonth, tc.lday, tc.leap, tc.system) + if err != nil { + t.Fatal(err) + } + descs := result.LunarDesc() + if len(descs) != 1 || descs[0] != tc.want { + t.Fatalf("unexpected descs: %v", descs) + } + infos := result.LunarInfo() + if len(infos) != 1 { + t.Fatalf("unexpected info count: %#v", infos) + } + info := infos[0] + if info.Dynasty != tc.dynasty || info.Emperor != tc.emperor || info.Nianhao != tc.nianhao || info.YearOfNianhao != tc.eraYear { + t.Fatalf("unexpected era info: %#v", info) + } + if info.LunarWithEraDesc != tc.want { + t.Fatalf("unexpected lunar era desc: %q", info.LunarWithEraDesc) + } + parsed, err := LunarToSolarWithCalendar(tc.want, tc.system) + if err != nil { + t.Fatal(err) + } + if len(parsed) != 1 || !parsed[0].Solar().Equal(result.Solar()) { + t.Fatalf("unexpected parsed result: %#v want %v", parsed, result.Solar()) + } + defaultParsed, err := LunarToSolar(tc.want) + if err != nil { + t.Fatal(err) + } + if len(defaultParsed) != 1 || !defaultParsed[0].Solar().Equal(result.Solar()) { + t.Fatalf("unexpected default parsed result: %#v want %v", defaultParsed, result.Solar()) + } + }) + } + + qinWang, err := LunarToSolarWithCalendar("秦王政元年十月初一", AncientCalendarZhuanxu) + if err != nil { + t.Fatal(err) + } + if len(qinWang) != 1 || qinWang[0].Lunar().LunarYear() != -245 || qinWang[0].Lunar().CalendarSystem() != AncientCalendarZhuanxu { + t.Fatalf("unexpected Qin Wang Zheng result: %#v", qinWang) + } + if _, err := LunarToSolar("秦王政元年十月初一"); err == nil { + t.Fatal("expected default parser to reject non-default Qin warring-state era") + } + if _, err := LunarToSolarWithCalendar("周安王元年后九月初一", AncientCalendarZhou); err == nil { + t.Fatal("expected non-Qin ancient era parser to reject hou month") + } +} + func Test_ChineseCalendarAncientPreQin(t *testing.T) { testData := []struct { name string @@ -841,6 +919,8 @@ func TestHistoricalEraRegression(t *testing.T) { "祥兴元年正月初一", "贞祐元年正月初一", "贞佑元年正月初一", + "前元元年正月初一", + "后元元年正月初一", "嘉佑元年正月初一", "元佑元年正月初一", "天佑元年正月初一", @@ -853,6 +933,13 @@ func TestHistoricalEraRegression(t *testing.T) { t.Fatalf("LunarToSolar(%q) returned no candidates", tc) } } + houyuan, err := LunarToSolar("后元元年正月初一") + if err != nil { + t.Fatal(err) + } + if len(houyuan) < 2 { + t.Fatalf("expected ancient and Han-Qing houyuan candidates, got %#v", houyuan) + } } /* diff --git a/calendar/time.go b/calendar/time.go index 8eb8a50..9b0d3b3 100644 --- a/calendar/time.go +++ b/calendar/time.go @@ -328,7 +328,7 @@ func (l LunarTime) innerDescWithNianHao(withEmperor bool, withDynasty bool) []st res = append(res, tmp) } } else { - res = append(res, number2Chinese(l.year, true)+"年"+l.desc) + res = append(res, lunarYearDesc(l.year)+"年"+l.desc) } return res } @@ -343,7 +343,7 @@ func (l LunarTime) LunarInfo() []LunarInfo { li := LunarInfo{ SolarDate: l.solarDate, LunarYear: l.year, - LunarYearChn: number2Chinese(l.year, true), + LunarYearChn: lunarYearDesc(l.year), LunarMonth: l.month, LunarDay: l.day, IsLeap: l.leap, @@ -367,7 +367,7 @@ func (l LunarTime) LunarInfo() []LunarInfo { li := LunarInfo{ SolarDate: l.solarDate, LunarYear: l.year, - LunarYearChn: number2Chinese(l.year, true), + LunarYearChn: lunarYearDesc(l.year), LunarMonth: l.month, LunarDay: l.day, IsLeap: l.leap, @@ -381,11 +381,18 @@ func (l LunarTime) LunarInfo() []LunarInfo { Emperor: "", Nianhao: "", YearOfNianhao: 0, - EraDesc: number2Chinese(l.year, true) + "年", - LunarWithEraDesc: number2Chinese(l.year, true) + "年" + l.desc, + EraDesc: lunarYearDesc(l.year) + "年", + LunarWithEraDesc: lunarYearDesc(l.year) + "年" + l.desc, ChineseZodiac: l.ShengXiao(), } res = append(res, li) } return res } + +func lunarYearDesc(year int) string { + if year <= 0 { + return "前" + number2Chinese(1-year, true) + } + return number2Chinese(year, true) +}