From 3692521e761bd1f8433ebd43a7cac95d9821d4ab Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 3 May 2024 10:16:00 +0000 Subject: [PATCH 1/8] This closes #1885,add more langNumFmtFunc Signed-off-by: wushiling50 <2531010934@qq.com> --- numfmt.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/numfmt.go b/numfmt.go index 47f2d4a56f..c56d5f02b3 100644 --- a/numfmt.go +++ b/numfmt.go @@ -57,6 +57,10 @@ const ( CultureNameUnknown CultureName = iota CultureNameEnUS CultureNameZhCN + CultureNameZhTW + CultureNameJaJP + CultureNameKoKR + CultureNameThTH ) var ( @@ -4754,6 +4758,54 @@ func (f *File) langNumFmtFuncZhCN(numFmtID int) string { 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] +} + +// 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] +} + +// langNumFmtFuncThTH returns number format code by given date and time pattern +// for country code th-th. +func (f *File) langNumFmtFuncThTH(numFmtID int) string { + if f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if f.options.LongTimePattern != "" { + return f.options.LongTimePattern + } + return langNumFmt["th-th"][numFmtID] +} + // getBuiltInNumFmtCode convert number format index to number format code with // specified locale and language. func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) { @@ -4767,6 +4819,18 @@ func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) { if f.options.CultureInfo == CultureNameZhCN { return f.langNumFmtFuncZhCN(numFmtID), true } + if f.options.CultureInfo == CultureNameZhTW { + return f.langNumFmtFuncZhTW(numFmtID), true + } + if f.options.CultureInfo == CultureNameJaJP { + return f.langNumFmtFuncJaJP(numFmtID), true + } + if f.options.CultureInfo == CultureNameKoKR { + return f.langNumFmtFuncKoKR(numFmtID), true + } + if f.options.CultureInfo == CultureNameThTH { + return f.langNumFmtFuncThTH(numFmtID), true + } } return "", false } From 98355a23bff888c0ef716280088435f37fd0b11f Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 3 May 2024 10:16:00 +0000 Subject: [PATCH 2/8] This closes #1885,add more langNumFmtFunc Signed-off-by: wushiling50 <2531010934@qq.com> --- numfmt.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/numfmt.go b/numfmt.go index c56d5f02b3..b995030ee0 100644 --- a/numfmt.go +++ b/numfmt.go @@ -4797,10 +4797,17 @@ func (f *File) langNumFmtFuncKoKR(numFmtID int) string { // langNumFmtFuncThTH returns number format code by given date and time pattern // for country code th-th. func (f *File) langNumFmtFuncThTH(numFmtID int) string { +<<<<<<< HEAD if f.options.ShortDatePattern != "" { return f.options.ShortDatePattern } if f.options.LongTimePattern != "" { +======= + if numFmtID == 71 && f.options.ShortDatePattern != "" { + return f.options.ShortDatePattern + } + if numFmtID == 76 && f.options.LongTimePattern != "" { +>>>>>>> f26dbfd (This closes #1885,add more langNumFmtFunc) return f.options.LongTimePattern } return langNumFmt["th-th"][numFmtID] From cc1290b92978d72b2df43b075d48f1b6b28fc12a Mon Sep 17 00:00:00 2001 From: wushiling50 <2531010934@qq.com> Date: Mon, 13 May 2024 23:12:07 +0800 Subject: [PATCH 3/8] This closes #1885,add langNumFmtFunc test Signed-off-by: wushiling50 <2531010934@qq.com> --- numfmt_test.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/numfmt_test.go b/numfmt_test.go index 49e4fa03be..bed50e30c9 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -3613,3 +3613,74 @@ func TestNumFmt(t *testing.T) { assert.Equal(t, ErrUnsupportedNumberFormat, err) assert.False(t, changeNumFmtCode) } + +func TestLangNumFmtFunc(t *testing.T) { + shortDatePattern, longTimePattern := "M/d/yy", "h:mm:ss" + t.Run("test langNumFmtFuncZhTW", func(t *testing.T) { + f := NewFile(Options{ + CultureInfo: CultureNameZhTW, + ShortDatePattern: shortDatePattern, + LongTimePattern: longTimePattern, + }) + for k, v := range langNumFmt["zh-tw"] { + if k == 30 { + assert.Equal(t, f.langNumFmtFuncZhTW(k), shortDatePattern) + } else if 32 <= k && k <= 33 { + assert.Equal(t, f.langNumFmtFuncZhTW(k), longTimePattern) + } else { + assert.Equal(t, f.langNumFmtFuncZhTW(k), v) + } + } + }) + + t.Run("test langNumFmtFuncJaJP", func(t *testing.T) { + f := NewFile(Options{ + CultureInfo: CultureNameJaJP, + ShortDatePattern: shortDatePattern, + LongTimePattern: longTimePattern, + }) + for k, v := range langNumFmt["ja-jp"] { + if k == 30 { + assert.Equal(t, f.langNumFmtFuncJaJP(k), shortDatePattern) + } else if 32 <= k && k <= 33 { + assert.Equal(t, f.langNumFmtFuncJaJP(k), longTimePattern) + } else { + assert.Equal(t, f.langNumFmtFuncJaJP(k), v) + } + } + }) + + t.Run("test langNumFmtFuncKoKR", func(t *testing.T) { + f := NewFile(Options{ + CultureInfo: CultureNameKoKR, + ShortDatePattern: shortDatePattern, + LongTimePattern: longTimePattern, + }) + for k, v := range langNumFmt["ko-kr"] { + if k == 30 { + assert.Equal(t, f.langNumFmtFuncKoKR(k), shortDatePattern) + } else if 32 <= k && k <= 33 { + assert.Equal(t, f.langNumFmtFuncKoKR(k), longTimePattern) + } else { + assert.Equal(t, f.langNumFmtFuncKoKR(k), v) + } + } + }) + + t.Run("test langNumFmtFuncThTH", func(t *testing.T) { + f := NewFile(Options{ + CultureInfo: CultureNameThTH, + ShortDatePattern: shortDatePattern, + LongTimePattern: longTimePattern, + }) + for k, v := range langNumFmt["th-th"] { + if k == 71 { + assert.Equal(t, f.langNumFmtFuncThTH(k), shortDatePattern) + } else if k == 76 { + assert.Equal(t, f.langNumFmtFuncThTH(k), longTimePattern) + } else { + assert.Equal(t, f.langNumFmtFuncThTH(k), v) + } + } + }) +} From 4ff2ffb7579fad4c3c7baf977425afea333be335 Mon Sep 17 00:00:00 2001 From: wushiling50 <2531010934@qq.com> Date: Mon, 13 May 2024 23:18:13 +0800 Subject: [PATCH 4/8] This closes #1885,add more langNumFmtFunc Signed-off-by: wushiling50 <2531010934@qq.com> --- numfmt.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/numfmt.go b/numfmt.go index b995030ee0..18eaa46d16 100644 --- a/numfmt.go +++ b/numfmt.go @@ -4797,17 +4797,10 @@ func (f *File) langNumFmtFuncKoKR(numFmtID int) string { // langNumFmtFuncThTH returns number format code by given date and time pattern // for country code th-th. func (f *File) langNumFmtFuncThTH(numFmtID int) string { -<<<<<<< HEAD - if f.options.ShortDatePattern != "" { - return f.options.ShortDatePattern - } - if f.options.LongTimePattern != "" { -======= if numFmtID == 71 && f.options.ShortDatePattern != "" { return f.options.ShortDatePattern } if numFmtID == 76 && f.options.LongTimePattern != "" { ->>>>>>> f26dbfd (This closes #1885,add more langNumFmtFunc) return f.options.LongTimePattern } return langNumFmt["th-th"][numFmtID] From b2d325fc99c2f0a02e638b29972291ba2abf5beb Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 13 Oct 2024 23:20:34 +0800 Subject: [PATCH 5/8] Add CultureNameJaJP and CultureNameZhTW enumeration value - Update unit tests - Support apply number format for the Republic of China year and the Japanese calendar years --- calc.go | 6 +- excelize_test.go | 4 + numfmt.go | 205 ++++++++++++++++++++++++++--------------------- numfmt_test.go | 83 +++---------------- 4 files changed, 134 insertions(+), 164 deletions(-) diff --git a/calc.go b/calc.go index 9784ea6059..0958fd417f 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,9 @@ func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg { symbol := map[CultureName]string{ CultureNameUnknown: "$", CultureNameEnUS: "$", + CultureNameJaJP: "¥", 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 7eb689fd21..1e9baf9b91 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -874,7 +874,9 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) { 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"}}, 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 +888,9 @@ 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"}}, 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 0490ec488b..4f62d476b8 100644 --- a/numfmt.go +++ b/numfmt.go @@ -57,11 +57,9 @@ type CultureName byte const ( CultureNameUnknown CultureName = iota CultureNameEnUS + CultureNameJaJP CultureNameZhCN CultureNameZhTW - CultureNameJaJP - CultureNameKoKR - CultureNameThTH ) var ( @@ -795,7 +793,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", @@ -1172,6 +1170,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), @@ -4638,6 +4640,21 @@ 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) + }, + 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. @@ -4698,6 +4715,42 @@ 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] +} + +// 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} { @@ -4774,66 +4827,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] -} - -// 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] -} - -// 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] -} - -// langNumFmtFuncThTH returns number format code by given date and time pattern -// for country code th-th. -func (f *File) langNumFmtFuncThTH(numFmtID int) string { - if numFmtID == 71 && f.options.ShortDatePattern != "" { - return f.options.ShortDatePattern - } - if numFmtID == 76 && f.options.LongTimePattern != "" { - return f.options.LongTimePattern - } - return langNumFmt["th-th"][numFmtID] -} - // getBuiltInNumFmtCode convert number format index to number format code with // specified locale and language. func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) { @@ -4841,23 +4834,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 f.options.CultureInfo == CultureNameZhTW { - return f.langNumFmtFuncZhTW(numFmtID), true - } - if f.options.CultureInfo == CultureNameJaJP { - return f.langNumFmtFuncJaJP(numFmtID), true - } - if f.options.CultureInfo == CultureNameKoKR { - return f.langNumFmtFuncKoKR(numFmtID), true - } - if f.options.CultureInfo == CultureNameThTH { - return f.langNumFmtFuncThTH(numFmtID), true + if fn, ok := langNumFmtFunc[f.options.CultureInfo]; ok { + return fn(f, numFmtID), true } } return "", false @@ -6976,17 +6954,8 @@ 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 { @@ -7025,6 +6994,58 @@ 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) + return + } + } +} + +// 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 + } + langInfo, _ := getSupportedLanguageInfo(nf.localCode) + if inStrSlice(langInfo.tags, "zh-TW", false) != -1 { + nf.republicOfChinaYearHandler(token, langInfo) + } + if inStrSlice(langInfo.tags, "ja-JP", false) != -1 { + nf.japaneseYearHandler(token, langInfo) + } +} + // 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 bf9f055481..369fbb04b3 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -289,6 +289,18 @@ 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]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"}, @@ -3668,74 +3680,3 @@ func TestNumFmt(t *testing.T) { assert.Equal(t, ErrUnsupportedNumberFormat, err) assert.False(t, changeNumFmtCode) } - -func TestLangNumFmtFunc(t *testing.T) { - shortDatePattern, longTimePattern := "M/d/yy", "h:mm:ss" - t.Run("test langNumFmtFuncZhTW", func(t *testing.T) { - f := NewFile(Options{ - CultureInfo: CultureNameZhTW, - ShortDatePattern: shortDatePattern, - LongTimePattern: longTimePattern, - }) - for k, v := range langNumFmt["zh-tw"] { - if k == 30 { - assert.Equal(t, f.langNumFmtFuncZhTW(k), shortDatePattern) - } else if 32 <= k && k <= 33 { - assert.Equal(t, f.langNumFmtFuncZhTW(k), longTimePattern) - } else { - assert.Equal(t, f.langNumFmtFuncZhTW(k), v) - } - } - }) - - t.Run("test langNumFmtFuncJaJP", func(t *testing.T) { - f := NewFile(Options{ - CultureInfo: CultureNameJaJP, - ShortDatePattern: shortDatePattern, - LongTimePattern: longTimePattern, - }) - for k, v := range langNumFmt["ja-jp"] { - if k == 30 { - assert.Equal(t, f.langNumFmtFuncJaJP(k), shortDatePattern) - } else if 32 <= k && k <= 33 { - assert.Equal(t, f.langNumFmtFuncJaJP(k), longTimePattern) - } else { - assert.Equal(t, f.langNumFmtFuncJaJP(k), v) - } - } - }) - - t.Run("test langNumFmtFuncKoKR", func(t *testing.T) { - f := NewFile(Options{ - CultureInfo: CultureNameKoKR, - ShortDatePattern: shortDatePattern, - LongTimePattern: longTimePattern, - }) - for k, v := range langNumFmt["ko-kr"] { - if k == 30 { - assert.Equal(t, f.langNumFmtFuncKoKR(k), shortDatePattern) - } else if 32 <= k && k <= 33 { - assert.Equal(t, f.langNumFmtFuncKoKR(k), longTimePattern) - } else { - assert.Equal(t, f.langNumFmtFuncKoKR(k), v) - } - } - }) - - t.Run("test langNumFmtFuncThTH", func(t *testing.T) { - f := NewFile(Options{ - CultureInfo: CultureNameThTH, - ShortDatePattern: shortDatePattern, - LongTimePattern: longTimePattern, - }) - for k, v := range langNumFmt["th-th"] { - if k == 71 { - assert.Equal(t, f.langNumFmtFuncThTH(k), shortDatePattern) - } else if k == 76 { - assert.Equal(t, f.langNumFmtFuncThTH(k), longTimePattern) - } else { - assert.Equal(t, f.langNumFmtFuncThTH(k), v) - } - } - }) -} From 86dc939da1416172f5eaf798f76b485249a76667 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 14 Oct 2024 00:42:35 +0800 Subject: [PATCH 6/8] Simplify code and add unit tests for number format --- numfmt.go | 15 ++++++++++----- numfmt_test.go | 5 +++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/numfmt.go b/numfmt.go index 4f62d476b8..ac46d8fd9b 100644 --- a/numfmt.go +++ b/numfmt.go @@ -6961,7 +6961,6 @@ func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo languageIn if year == -1 { return } - langInfo, _ := getSupportedLanguageInfo(nf.localCode) nf.useGannen = langInfo.useGannen switch len(token.TValue) { case 1: @@ -6972,7 +6971,6 @@ func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo languageIn default: nf.result += japaneseEraNames[i] } - return } if strings.Contains(strings.ToUpper(token.TValue), "E") { _, year := eraYear(nf.t) @@ -7021,7 +7019,6 @@ func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, langInfo lan } if len(token.TValue) == 1 && !nf.useGannen { nf.result += strconv.Itoa(year) - return } } } @@ -7038,11 +7035,19 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) { return } langInfo, _ := getSupportedLanguageInfo(nf.localCode) - if inStrSlice(langInfo.tags, "zh-TW", false) != -1 { + 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 { + 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 } } diff --git a/numfmt_test.go b/numfmt_test.go index 369fbb04b3..158104755e 100644 --- a/numfmt_test.go +++ b/numfmt_test.go @@ -289,6 +289,8 @@ 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"}, @@ -2734,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日"}, From a6f73ee3cddc2043650e7706bab58f8ffa5dadcf Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 14 Oct 2024 12:47:39 +0800 Subject: [PATCH 7/8] Add CultureNameKoKR enumeration value - Update unit tests - Support apply number format for the Korean Danki calendar --- calc.go | 1 + excelize_test.go | 7 ++++++- numfmt.go | 26 +++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/calc.go b/calc.go index 0958fd417f..976ee53dd2 100644 --- a/calc.go +++ b/calc.go @@ -16381,6 +16381,7 @@ func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg { CultureNameUnknown: "$", CultureNameEnUS: "$", CultureNameJaJP: "¥", + CultureNameKoKR: "\u20a9", CultureNameZhCN: "¥", CultureNameZhTW: "NT$", }[fn.f.options.CultureInfo] diff --git a/excelize_test.go b/excelize_test.go index 1e9baf9b91..5fdbff4647 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -870,11 +870,15 @@ 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 := [][]string{make([]string, 42)} + for i := 0; i < 42; i++ { + rawCellValues[0][i] = "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"}}, } { @@ -889,6 +893,7 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) { 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"}}, } { diff --git a/numfmt.go b/numfmt.go index ac46d8fd9b..9a963979fe 100644 --- a/numfmt.go +++ b/numfmt.go @@ -58,6 +58,7 @@ const ( CultureNameUnknown CultureName = iota CultureNameEnUS CultureNameJaJP + CultureNameKoKR CultureNameZhCN CultureNameZhTW ) @@ -4648,6 +4649,9 @@ var ( 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) }, @@ -4727,6 +4731,18 @@ func (f *File) langNumFmtFuncJaJP(numFmtID int) string { 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 { @@ -7026,15 +7042,19 @@ func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, langInfo lan // 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(nf.t.Year())[2:] + nf.result += strconv.Itoa(year)[2:] return } - nf.result += strconv.Itoa(nf.t.Year()) + nf.result += strconv.Itoa(year) return } - langInfo, _ := getSupportedLanguageInfo(nf.localCode) if inStrSlice(langInfo.tags, "zh-TW", false) != -1 || nf.opts != nil && nf.opts.CultureInfo == CultureNameZhTW { nf.republicOfChinaYearHandler(token, langInfo) From 0f343c075baca01891abef1e689ff3fce74f6686 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 14 Oct 2024 13:37:46 +0800 Subject: [PATCH 8/8] This fixed unit tests error --- excelize_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/excelize_test.go b/excelize_test.go index 5fdbff4647..94cf18441f 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -870,9 +870,9 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) { } func TestSetCellStyleLangNumberFormat(t *testing.T) { - rawCellValues := [][]string{make([]string, 42)} + rawCellValues := make([][]string, 42) for i := 0; i < 42; i++ { - rawCellValues[0][i] = "45162" + rawCellValues[i] = []string{"45162"} } for lang, expected := range map[CultureName][][]string{ CultureNameUnknown: rawCellValues,