From d1937a0cde23ff87549e59ef261a19d65b735c7b Mon Sep 17 00:00:00 2001 From: wushiling50 <120616893+wushiling50@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:36:04 +0800 Subject: [PATCH] This closes #1885, add new CultureNameJaJP, CultureNameKoKR and CultureNameZhTW enumeration values (#1895) - Support apply number format for the Japanese calendar years, the Korean Danki calendar and the Republic of China year - Update unit tests Signed-off-by: wushiling50 <2531010934@qq.com> --- calc.go | 7 +- excelize_test.go | 11 ++- numfmt.go | 172 ++++++++++++++++++++++++++++++++++++++--------- numfmt_test.go | 17 +++++ 4 files changed, 174 insertions(+), 33 deletions(-) diff --git a/calc.go b/calc.go index 9784ea6..976ee53 100644 --- a/calc.go +++ b/calc.go @@ -13629,7 +13629,9 @@ func (fn *formulaFuncs) DBCS(argsList *list.List) formulaArg { if arg.Type == ArgError { return arg } - if fn.f.options.CultureInfo == CultureNameZhCN { + if fn.f.options.CultureInfo == CultureNameJaJP || + fn.f.options.CultureInfo == CultureNameZhCN || + fn.f.options.CultureInfo == CultureNameZhTW { var chars []string for _, r := range arg.Value() { code := r @@ -16378,7 +16380,10 @@ func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg { symbol := map[CultureName]string{ CultureNameUnknown: "$", CultureNameEnUS: "$", + CultureNameJaJP: "¥", + CultureNameKoKR: "\u20a9", CultureNameZhCN: "¥", + CultureNameZhTW: "NT$", }[fn.f.options.CultureInfo] numFmtCode := fmt.Sprintf("%s#,##0%s%s;(%s#,##0%s%s)", symbol, dot, strings.Repeat("0", decimals), symbol, dot, strings.Repeat("0", decimals)) diff --git a/excelize_test.go b/excelize_test.go index 7eb689f..94cf184 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -870,11 +870,17 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) { } func TestSetCellStyleLangNumberFormat(t *testing.T) { - rawCellValues := [][]string{{"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}} + rawCellValues := make([][]string, 42) + for i := 0; i < 42; i++ { + rawCellValues[i] = []string{"45162"} + } for lang, expected := range map[CultureName][][]string{ CultureNameUnknown: rawCellValues, CultureNameEnUS: {{"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"0:00:00"}, {"45162"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"8/24/23"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameJaJP: {{"R5.8.24"}, {"令和5年8月24日"}, {"令和5年8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"0時00分"}, {"0時00分00秒"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"R5.8.24"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"令和5年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameKoKR: [][]string{[]string{"4356年 08月 24日"}, []string{"08-24"}, []string{"08-24"}, []string{"08-24-56"}, []string{"4356년 08월 24일"}, []string{"0시 00분"}, []string{"0시 00분 00초"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"4356年 08月 24日"}, []string{"4356年 08月 24日"}, []string{"08-24"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"08-24"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"4356年 08月 24日"}, []string{"08-24"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}}, CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"0时00分"}, {"0时00分00秒"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameZhTW: {{"112/8/24"}, {"112年8月24日"}, {"112年8月24日"}, {"8/24/23"}, {"2023年8月24日"}, {"00時00分"}, {"00時00分00秒"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112/8/24"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, } { f, err := prepareTestBook5(Options{CultureInfo: lang}) assert.NoError(t, err) @@ -886,7 +892,10 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) { // Test apply language number format code with date and time pattern for lang, expected := range map[CultureName][][]string{ CultureNameEnUS: {{"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"00:00:00"}, {"45162"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"2023-8-24"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameJaJP: {{"R5.8.24"}, {"令和5年8月24日"}, {"令和5年8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"R5.8.24"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"令和5年8月24日"}, {"2023年8月"}, {"8月24日"}, {"R5.8.24"}, {"令和5年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameKoKR: [][]string{[]string{"4356年 08月 24日"}, []string{"08-24"}, []string{"08-24"}, []string{"4356-8-24"}, []string{"4356년 08월 24일"}, []string{"00:00:00"}, []string{"00:00:00"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"4356年 08月 24日"}, []string{"4356年 08月 24日"}, []string{"08-24"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"08-24"}, []string{"4356-08-24"}, []string{"4356-08-24"}, []string{"4356年 08月 24日"}, []string{"08-24"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}, []string{"45162"}}, CultureNameZhCN: {{"2023年8月"}, {"8月24日"}, {"8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"2023年8月"}, {"8月24日"}, {"2023年8月"}, {"8月24日"}, {"8月24日"}, {"上午12时00分"}, {"上午12时00分00秒"}, {"2023年8月"}, {"8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, + CultureNameZhTW: {{"112/8/24"}, {"112年8月24日"}, {"112年8月24日"}, {"2023-8-24"}, {"2023年8月24日"}, {"00:00:00"}, {"00:00:00"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112/8/24"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112年8月24日"}, {"上午12時00分"}, {"上午12時00分00秒"}, {"112/8/24"}, {"112年8月24日"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}, {"45162"}}, } { f, err := prepareTestBook5(Options{CultureInfo: lang, ShortDatePattern: "yyyy-M-d", LongTimePattern: "hh:mm:ss"}) assert.NoError(t, err) diff --git a/numfmt.go b/numfmt.go index 265fe28..9a96397 100644 --- a/numfmt.go +++ b/numfmt.go @@ -57,7 +57,10 @@ type CultureName byte const ( CultureNameUnknown CultureName = iota CultureNameEnUS + CultureNameJaJP + CultureNameKoKR CultureNameZhCN + CultureNameZhTW ) var ( @@ -791,7 +794,7 @@ var ( 31748: {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2}, 3076: {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2}, 5124: {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2}, - 1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2}, + 1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2, useGannen: true}, 9: {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0], weekdayNames: weekdayNamesEnglish, weekdayNamesAbbr: weekdayNamesEnglishAbbr}, 4096: {tags: []string{ "aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML", @@ -1168,6 +1171,10 @@ var ( "JA-JP-X-GANNEN": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr}, "JA-JP-X-GANNEN,80": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr, useGannen: true}, } + // republicOfChinaYear defined start time of the Republic of China + republicOfChinaYear = time.Date(1912, time.January, 1, 0, 0, 0, 0, time.UTC) + // republicOfChinaEraName defined the Republic of China era name for the Republic of China calendar. + republicOfChinaEraName = []string{"\u4e2d\u83ef\u6c11\u570b", "\u6c11\u570b", "\u524d"} // japaneseEraYears list the Japanese era name periods. japaneseEraYears = []time.Time{ time.Date(1868, time.August, 8, 0, 0, 0, 0, time.UTC), @@ -4634,6 +4641,24 @@ var ( return r.Replace(s) }, } + // langNumFmtFunc defines functions to apply language number format code. + langNumFmtFunc = map[CultureName]func(f *File, numFmtID int) string{ + CultureNameEnUS: func(f *File, numFmtID int) string { + return f.langNumFmtFuncEnUS(numFmtID) + }, + CultureNameJaJP: func(f *File, numFmtID int) string { + return f.langNumFmtFuncJaJP(numFmtID) + }, + CultureNameKoKR: func(f *File, numFmtID int) string { + return f.langNumFmtFuncKoKR(numFmtID) + }, + CultureNameZhCN: func(f *File, numFmtID int) string { + return f.langNumFmtFuncZhCN(numFmtID) + }, + CultureNameZhTW: func(f *File, numFmtID int) string { + return f.langNumFmtFuncZhTW(numFmtID) + }, + } ) // getSupportedLanguageInfo returns language infomation by giving language code. @@ -4694,6 +4719,54 @@ func (f *File) langNumFmtFuncEnUS(numFmtID int) string { return "" } +// langNumFmtFuncJaJP returns number format code by given date and time pattern +// for country code ja-jp. +func (f *File) langNumFmtFuncJaJP(numFmtID int) string { + if numFmtID == 30 && f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" { + return f.options.LongTimePattern + } + return langNumFmt["ja-jp"][numFmtID] +} + +// langNumFmtFuncKoKR returns number format code by given date and time pattern +// for country code ko-kr. +func (f *File) langNumFmtFuncKoKR(numFmtID int) string { + if numFmtID == 30 && f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" { + return f.options.LongTimePattern + } + return langNumFmt["ko-kr"][numFmtID] +} + +// langNumFmtFuncZhCN returns number format code by given date and time pattern +// for country code zh-cn. +func (f *File) langNumFmtFuncZhCN(numFmtID int) string { + if numFmtID == 30 && f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" { + return f.options.LongTimePattern + } + return langNumFmt["zh-cn"][numFmtID] +} + +// langNumFmtFuncZhTW returns number format code by given date and time pattern +// for country code zh-tw. +func (f *File) langNumFmtFuncZhTW(numFmtID int) string { + if numFmtID == 30 && f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" { + return f.options.LongTimePattern + } + return langNumFmt["zh-tw"][numFmtID] +} + // checkDateTimePattern check and validate date and time options field value. func (f *File) checkDateTimePattern() error { for _, pattern := range []string{f.options.LongDatePattern, f.options.LongTimePattern, f.options.ShortDatePattern} { @@ -4770,18 +4843,6 @@ func (f *File) extractNumFmtDecimal(fmtCode string) int { return -1 } -// langNumFmtFuncZhCN returns number format code by given date and time pattern -// for country code zh-cn. -func (f *File) langNumFmtFuncZhCN(numFmtID int) string { - if numFmtID == 30 && f.options.ShortDatePattern != "" { - return f.options.ShortDatePattern - } - if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" { - return f.options.LongTimePattern - } - return langNumFmt["zh-cn"][numFmtID] -} - // getBuiltInNumFmtCode convert number format index to number format code with // specified locale and language. func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) { @@ -4789,11 +4850,8 @@ func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) { return fmtCode, true } if isLangNumFmt(numFmtID) { - if f.options.CultureInfo == CultureNameEnUS { - return f.langNumFmtFuncEnUS(numFmtID), true - } - if f.options.CultureInfo == CultureNameZhCN { - return f.langNumFmtFuncZhCN(numFmtID), true + if fn, ok := langNumFmtFunc[f.options.CultureInfo]; ok { + return fn(f, numFmtID), true } } return "", false @@ -6912,23 +6970,13 @@ func eraYear(t time.Time) (int, int) { return i, year } -// yearsHandler will be handling years in the date and times types tokens for a -// number format expression. -func (nf *numberFormat) yearsHandler(token nfp.Token) { - if strings.Contains(strings.ToUpper(token.TValue), "Y") { - if len(token.TValue) <= 2 { - nf.result += strconv.Itoa(nf.t.Year())[2:] - return - } - nf.result += strconv.Itoa(nf.t.Year()) - return - } +// japaneseYearHandler handling the Japanease calendar years. +func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo languageInfo) { if strings.Contains(strings.ToUpper(token.TValue), "G") { i, year := eraYear(nf.t) if year == -1 { return } - langInfo, _ := getSupportedLanguageInfo(nf.localCode) nf.useGannen = langInfo.useGannen switch len(token.TValue) { case 1: @@ -6939,7 +6987,6 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) { default: nf.result += japaneseEraNames[i] } - return } if strings.Contains(strings.ToUpper(token.TValue), "E") { _, year := eraYear(nf.t) @@ -6961,6 +7008,69 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) { } } +// republicOfChinaYearHandler handling the Republic of China calendar years. +func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, langInfo languageInfo) { + if strings.Contains(strings.ToUpper(token.TValue), "G") { + year := nf.t.Year() - republicOfChinaYear.Year() + 1 + if year == 1 { + nf.useGannen = langInfo.useGannen + } + var name string + if name = republicOfChinaEraName[0]; len(token.TValue) < 3 { + name = republicOfChinaEraName[1] + } + if year < 0 { + name += republicOfChinaEraName[2] + } + nf.result += name + } + if strings.Contains(strings.ToUpper(token.TValue), "E") { + year := nf.t.Year() - republicOfChinaYear.Year() + 1 + if year < 0 { + year = republicOfChinaYear.Year() - nf.t.Year() + } + if year == 1 && nf.useGannen { + nf.result += "\u5143" + return + } + if len(token.TValue) == 1 && !nf.useGannen { + nf.result += strconv.Itoa(year) + } + } +} + +// yearsHandler will be handling years in the date and times types tokens for a +// number format expression. +func (nf *numberFormat) yearsHandler(token nfp.Token) { + langInfo, _ := getSupportedLanguageInfo(nf.localCode) + if strings.Contains(strings.ToUpper(token.TValue), "Y") { + year := nf.t.Year() + if nf.opts != nil && nf.opts.CultureInfo == CultureNameKoKR { + year += 2333 + } + if len(token.TValue) <= 2 { + nf.result += strconv.Itoa(year)[2:] + return + } + nf.result += strconv.Itoa(year) + return + } + if inStrSlice(langInfo.tags, "zh-TW", false) != -1 || + nf.opts != nil && nf.opts.CultureInfo == CultureNameZhTW { + nf.republicOfChinaYearHandler(token, langInfo) + return + } + if inStrSlice(langInfo.tags, "ja-JP", false) != -1 || + nf.opts != nil && nf.opts.CultureInfo == CultureNameJaJP { + nf.japaneseYearHandler(token, langInfo) + return + } + if strings.Contains(strings.ToUpper(token.TValue), "E") { + nf.result += strconv.Itoa(nf.t.Year()) + return + } +} + // daysHandler will be handling days in the date and times types tokens for a // number format expression. func (nf *numberFormat) daysHandler(token nfp.Token) { diff --git a/numfmt_test.go b/numfmt_test.go index c3e1a99..1581047 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -289,6 +289,20 @@ func TestNumFmt(t *testing.T) { {"43543.503206018519", "[$-401]mmmm dd yyyy h:mm AM/PM aaa", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"}, {"43543.503206018519", "[$-401]mmmmm dd yyyy h:mm AM/PM ddd", "\u0645 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"}, {"43543.503206018519", "[$-401]mmmmmm dd yyyy h:mm AM/PM dddd", "\u0645\u0627\u0631\u0633 19 2019 12:04 \u0645 \u0627\u0644\u062B\u0644\u0627\u062B\u0627\u0621"}, + {"43466.189571759256", "[$-404]g\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5e74\u0031\u6708\u0031\u65e5"}, + {"43466.189571759256", "[$-404]e\"年\"m\"月\"d\"日\";@", "\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"}, + {"43466.189571759256", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"}, + {"43466.189571759256", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"}, + {"43466.189571759256", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"}, + {"43466.189571759256", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u0031\u0030\u0038\u5e74\u0031\u6708\u0031\u65e5"}, + {"4385.5083333333332", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"}, + {"4385.5083333333332", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"}, + {"4385.5083333333332", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"}, + {"4385.5083333333332", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u5143\u5e74\u0031\u6708\u0032\u65e5"}, + {"123", "[$-404]ge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"}, + {"123", "[$-404]gge\"年\"m\"月\"d\"日\";@", "\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"}, + {"123", "[$-404]ggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"}, + {"123", "[$-404]gggge\"年\"m\"月\"d\"日\";@", "\u4e2d\u83ef\u6c11\u570b\u524d\u0031\u0032\u5e74\u0035\u6708\u0032\u65e5"}, {"44562.189571759256", "[$-1010401]mmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"}, {"44562.189571759256", "[$-1010401]mmmm dd yyyy h:mm AM/PM", "\u064A\u0646\u0627\u064A\u0631 01 2022 4:32 \u0635"}, {"44562.189571759256", "[$-1010401]mmmmm dd yyyy h:mm AM/PM", "\u064A 01 2022 4:32 \u0635"}, @@ -2722,6 +2736,9 @@ func TestNumFmt(t *testing.T) { {"44835.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM aaa", "\u0e15 01 2022 4:32 AM \u0E2A."}, {"44866.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM ddd", "\u0e1e 01 2022 4:32 AM \u0E2D."}, {"44896.18957170139", "[$-41E]mmmmm dd yyyy h:mm AM/PM dddd", "\u0e18 01 2022 4:32 AM \u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35"}, + {"100", "g\"年\"m\"月\"d\"日\";@", "年4月9日"}, + {"100", "e\"年\"m\"月\"d\"日\";@", "1900年4月9日"}, + {"100", "ge\"年\"m\"月\"d\"日\";@", "1900年4月9日"}, {"100", "[$-411]ge\"年\"m\"月\"d\"日\";@", "1900年4月9日"}, {"43709", "[$-411]ge\"年\"m\"月\"d\"日\";@", "R1年9月1日"}, {"43709", "[$-411]gge\"年\"m\"月\"d\"日\";@", "\u4EE41年9月1日"},