Skip to content

Commit b2d325f

Browse files
committed
Add CultureNameJaJP and CultureNameZhTW enumeration value
- Update unit tests - Support apply number format for the Republic of China year and the Japanese calendar years
1 parent 1f129d3 commit b2d325f

File tree

4 files changed

+134
-164
lines changed

4 files changed

+134
-164
lines changed

calc.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13629,7 +13629,9 @@ func (fn *formulaFuncs) DBCS(argsList *list.List) formulaArg {
1362913629
if arg.Type == ArgError {
1363013630
return arg
1363113631
}
13632-
if fn.f.options.CultureInfo == CultureNameZhCN {
13632+
if fn.f.options.CultureInfo == CultureNameJaJP ||
13633+
fn.f.options.CultureInfo == CultureNameZhCN ||
13634+
fn.f.options.CultureInfo == CultureNameZhTW {
1363313635
var chars []string
1363413636
for _, r := range arg.Value() {
1363513637
code := r
@@ -16378,7 +16380,9 @@ func (fn *formulaFuncs) DOLLAR(argsList *list.List) formulaArg {
1637816380
symbol := map[CultureName]string{
1637916381
CultureNameUnknown: "$",
1638016382
CultureNameEnUS: "$",
16383+
CultureNameJaJP: "¥",
1638116384
CultureNameZhCN: "¥",
16385+
CultureNameZhTW: "NT$",
1638216386
}[fn.f.options.CultureInfo]
1638316387
numFmtCode := fmt.Sprintf("%s#,##0%s%s;(%s#,##0%s%s)",
1638416388
symbol, dot, strings.Repeat("0", decimals), symbol, dot, strings.Repeat("0", decimals))

excelize_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,9 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) {
874874
for lang, expected := range map[CultureName][][]string{
875875
CultureNameUnknown: rawCellValues,
876876
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"}},
877+
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"}},
877878
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"}},
879+
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"}},
878880
} {
879881
f, err := prepareTestBook5(Options{CultureInfo: lang})
880882
assert.NoError(t, err)
@@ -886,7 +888,9 @@ func TestSetCellStyleLangNumberFormat(t *testing.T) {
886888
// Test apply language number format code with date and time pattern
887889
for lang, expected := range map[CultureName][][]string{
888890
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"}},
891+
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"}},
889892
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"}},
893+
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"}},
890894
} {
891895
f, err := prepareTestBook5(Options{CultureInfo: lang, ShortDatePattern: "yyyy-M-d", LongTimePattern: "hh:mm:ss"})
892896
assert.NoError(t, err)

numfmt.go

Lines changed: 113 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,9 @@ type CultureName byte
5757
const (
5858
CultureNameUnknown CultureName = iota
5959
CultureNameEnUS
60+
CultureNameJaJP
6061
CultureNameZhCN
6162
CultureNameZhTW
62-
CultureNameJaJP
63-
CultureNameKoKR
64-
CultureNameThTH
6563
)
6664

6765
var (
@@ -795,7 +793,7 @@ var (
795793
31748: {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
796794
3076: {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
797795
5124: {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
798-
1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2},
796+
1028: {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2], weekdayNames: weekdayNamesChinese, weekdayNamesAbbr: weekdayNamesChineseAbbr2, useGannen: true},
799797
9: {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0], weekdayNames: weekdayNamesEnglish, weekdayNamesAbbr: weekdayNamesEnglishAbbr},
800798
4096: {tags: []string{
801799
"aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML",
@@ -1172,6 +1170,10 @@ var (
11721170
"JA-JP-X-GANNEN": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr},
11731171
"JA-JP-X-GANNEN,80": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese, weekdayNames: weekdayNamesJapanese, weekdayNamesAbbr: weekdayNamesJapaneseAbbr, useGannen: true},
11741172
}
1173+
// republicOfChinaYear defined start time of the Republic of China
1174+
republicOfChinaYear = time.Date(1912, time.January, 1, 0, 0, 0, 0, time.UTC)
1175+
// republicOfChinaEraName defined the Republic of China era name for the Republic of China calendar.
1176+
republicOfChinaEraName = []string{"\u4e2d\u83ef\u6c11\u570b", "\u6c11\u570b", "\u524d"}
11751177
// japaneseEraYears list the Japanese era name periods.
11761178
japaneseEraYears = []time.Time{
11771179
time.Date(1868, time.August, 8, 0, 0, 0, 0, time.UTC),
@@ -4638,6 +4640,21 @@ var (
46384640
return r.Replace(s)
46394641
},
46404642
}
4643+
// langNumFmtFunc defines functions to apply language number format code.
4644+
langNumFmtFunc = map[CultureName]func(f *File, numFmtID int) string{
4645+
CultureNameEnUS: func(f *File, numFmtID int) string {
4646+
return f.langNumFmtFuncEnUS(numFmtID)
4647+
},
4648+
CultureNameJaJP: func(f *File, numFmtID int) string {
4649+
return f.langNumFmtFuncJaJP(numFmtID)
4650+
},
4651+
CultureNameZhCN: func(f *File, numFmtID int) string {
4652+
return f.langNumFmtFuncZhCN(numFmtID)
4653+
},
4654+
CultureNameZhTW: func(f *File, numFmtID int) string {
4655+
return f.langNumFmtFuncZhTW(numFmtID)
4656+
},
4657+
}
46414658
)
46424659

46434660
// getSupportedLanguageInfo returns language infomation by giving language code.
@@ -4698,6 +4715,42 @@ func (f *File) langNumFmtFuncEnUS(numFmtID int) string {
46984715
return ""
46994716
}
47004717

4718+
// langNumFmtFuncJaJP returns number format code by given date and time pattern
4719+
// for country code ja-jp.
4720+
func (f *File) langNumFmtFuncJaJP(numFmtID int) string {
4721+
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4722+
return f.options.ShortDatePattern
4723+
}
4724+
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4725+
return f.options.LongTimePattern
4726+
}
4727+
return langNumFmt["ja-jp"][numFmtID]
4728+
}
4729+
4730+
// langNumFmtFuncZhCN returns number format code by given date and time pattern
4731+
// for country code zh-cn.
4732+
func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
4733+
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4734+
return f.options.ShortDatePattern
4735+
}
4736+
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4737+
return f.options.LongTimePattern
4738+
}
4739+
return langNumFmt["zh-cn"][numFmtID]
4740+
}
4741+
4742+
// langNumFmtFuncZhTW returns number format code by given date and time pattern
4743+
// for country code zh-tw.
4744+
func (f *File) langNumFmtFuncZhTW(numFmtID int) string {
4745+
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4746+
return f.options.ShortDatePattern
4747+
}
4748+
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4749+
return f.options.LongTimePattern
4750+
}
4751+
return langNumFmt["zh-tw"][numFmtID]
4752+
}
4753+
47014754
// checkDateTimePattern check and validate date and time options field value.
47024755
func (f *File) checkDateTimePattern() error {
47034756
for _, pattern := range []string{f.options.LongDatePattern, f.options.LongTimePattern, f.options.ShortDatePattern} {
@@ -4774,90 +4827,15 @@ func (f *File) extractNumFmtDecimal(fmtCode string) int {
47744827
return -1
47754828
}
47764829

4777-
// langNumFmtFuncZhCN returns number format code by given date and time pattern
4778-
// for country code zh-cn.
4779-
func (f *File) langNumFmtFuncZhCN(numFmtID int) string {
4780-
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4781-
return f.options.ShortDatePattern
4782-
}
4783-
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4784-
return f.options.LongTimePattern
4785-
}
4786-
return langNumFmt["zh-cn"][numFmtID]
4787-
}
4788-
4789-
// langNumFmtFuncZhTW returns number format code by given date and time pattern
4790-
// for country code zh-tw.
4791-
func (f *File) langNumFmtFuncZhTW(numFmtID int) string {
4792-
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4793-
return f.options.ShortDatePattern
4794-
}
4795-
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4796-
return f.options.LongTimePattern
4797-
}
4798-
return langNumFmt["zh-tw"][numFmtID]
4799-
}
4800-
4801-
// langNumFmtFuncJaJP returns number format code by given date and time pattern
4802-
// for country code ja-jp.
4803-
func (f *File) langNumFmtFuncJaJP(numFmtID int) string {
4804-
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4805-
return f.options.ShortDatePattern
4806-
}
4807-
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4808-
return f.options.LongTimePattern
4809-
}
4810-
return langNumFmt["ja-jp"][numFmtID]
4811-
}
4812-
4813-
// langNumFmtFuncKoKR returns number format code by given date and time pattern
4814-
// for country code ko-kr.
4815-
func (f *File) langNumFmtFuncKoKR(numFmtID int) string {
4816-
if numFmtID == 30 && f.options.ShortDatePattern != "" {
4817-
return f.options.ShortDatePattern
4818-
}
4819-
if (32 <= numFmtID && numFmtID <= 33) && f.options.LongTimePattern != "" {
4820-
return f.options.LongTimePattern
4821-
}
4822-
return langNumFmt["ko-kr"][numFmtID]
4823-
}
4824-
4825-
// langNumFmtFuncThTH returns number format code by given date and time pattern
4826-
// for country code th-th.
4827-
func (f *File) langNumFmtFuncThTH(numFmtID int) string {
4828-
if numFmtID == 71 && f.options.ShortDatePattern != "" {
4829-
return f.options.ShortDatePattern
4830-
}
4831-
if numFmtID == 76 && f.options.LongTimePattern != "" {
4832-
return f.options.LongTimePattern
4833-
}
4834-
return langNumFmt["th-th"][numFmtID]
4835-
}
4836-
48374830
// getBuiltInNumFmtCode convert number format index to number format code with
48384831
// specified locale and language.
48394832
func (f *File) getBuiltInNumFmtCode(numFmtID int) (string, bool) {
48404833
if fmtCode, ok := builtInNumFmt[numFmtID]; ok {
48414834
return fmtCode, true
48424835
}
48434836
if isLangNumFmt(numFmtID) {
4844-
if f.options.CultureInfo == CultureNameEnUS {
4845-
return f.langNumFmtFuncEnUS(numFmtID), true
4846-
}
4847-
if f.options.CultureInfo == CultureNameZhCN {
4848-
return f.langNumFmtFuncZhCN(numFmtID), true
4849-
}
4850-
if f.options.CultureInfo == CultureNameZhTW {
4851-
return f.langNumFmtFuncZhTW(numFmtID), true
4852-
}
4853-
if f.options.CultureInfo == CultureNameJaJP {
4854-
return f.langNumFmtFuncJaJP(numFmtID), true
4855-
}
4856-
if f.options.CultureInfo == CultureNameKoKR {
4857-
return f.langNumFmtFuncKoKR(numFmtID), true
4858-
}
4859-
if f.options.CultureInfo == CultureNameThTH {
4860-
return f.langNumFmtFuncThTH(numFmtID), true
4837+
if fn, ok := langNumFmtFunc[f.options.CultureInfo]; ok {
4838+
return fn(f, numFmtID), true
48614839
}
48624840
}
48634841
return "", false
@@ -6976,17 +6954,8 @@ func eraYear(t time.Time) (int, int) {
69766954
return i, year
69776955
}
69786956

6979-
// yearsHandler will be handling years in the date and times types tokens for a
6980-
// number format expression.
6981-
func (nf *numberFormat) yearsHandler(token nfp.Token) {
6982-
if strings.Contains(strings.ToUpper(token.TValue), "Y") {
6983-
if len(token.TValue) <= 2 {
6984-
nf.result += strconv.Itoa(nf.t.Year())[2:]
6985-
return
6986-
}
6987-
nf.result += strconv.Itoa(nf.t.Year())
6988-
return
6989-
}
6957+
// japaneseYearHandler handling the Japanease calendar years.
6958+
func (nf *numberFormat) japaneseYearHandler(token nfp.Token, langInfo languageInfo) {
69906959
if strings.Contains(strings.ToUpper(token.TValue), "G") {
69916960
i, year := eraYear(nf.t)
69926961
if year == -1 {
@@ -7025,6 +6994,58 @@ func (nf *numberFormat) yearsHandler(token nfp.Token) {
70256994
}
70266995
}
70276996

6997+
// republicOfChinaYearHandler handling the Republic of China calendar years.
6998+
func (nf *numberFormat) republicOfChinaYearHandler(token nfp.Token, langInfo languageInfo) {
6999+
if strings.Contains(strings.ToUpper(token.TValue), "G") {
7000+
year := nf.t.Year() - republicOfChinaYear.Year() + 1
7001+
if year == 1 {
7002+
nf.useGannen = langInfo.useGannen
7003+
}
7004+
var name string
7005+
if name = republicOfChinaEraName[0]; len(token.TValue) < 3 {
7006+
name = republicOfChinaEraName[1]
7007+
}
7008+
if year < 0 {
7009+
name += republicOfChinaEraName[2]
7010+
}
7011+
nf.result += name
7012+
}
7013+
if strings.Contains(strings.ToUpper(token.TValue), "E") {
7014+
year := nf.t.Year() - republicOfChinaYear.Year() + 1
7015+
if year < 0 {
7016+
year = republicOfChinaYear.Year() - nf.t.Year()
7017+
}
7018+
if year == 1 && nf.useGannen {
7019+
nf.result += "\u5143"
7020+
return
7021+
}
7022+
if len(token.TValue) == 1 && !nf.useGannen {
7023+
nf.result += strconv.Itoa(year)
7024+
return
7025+
}
7026+
}
7027+
}
7028+
7029+
// yearsHandler will be handling years in the date and times types tokens for a
7030+
// number format expression.
7031+
func (nf *numberFormat) yearsHandler(token nfp.Token) {
7032+
if strings.Contains(strings.ToUpper(token.TValue), "Y") {
7033+
if len(token.TValue) <= 2 {
7034+
nf.result += strconv.Itoa(nf.t.Year())[2:]
7035+
return
7036+
}
7037+
nf.result += strconv.Itoa(nf.t.Year())
7038+
return
7039+
}
7040+
langInfo, _ := getSupportedLanguageInfo(nf.localCode)
7041+
if inStrSlice(langInfo.tags, "zh-TW", false) != -1 {
7042+
nf.republicOfChinaYearHandler(token, langInfo)
7043+
}
7044+
if inStrSlice(langInfo.tags, "ja-JP", false) != -1 {
7045+
nf.japaneseYearHandler(token, langInfo)
7046+
}
7047+
}
7048+
70287049
// daysHandler will be handling days in the date and times types tokens for a
70297050
// number format expression.
70307051
func (nf *numberFormat) daysHandler(token nfp.Token) {

0 commit comments

Comments
 (0)