numfmt.go 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. // Copyright 2016 - 2023 The excelize Authors. All rights reserved. Use of
  2. // this source code is governed by a BSD-style license that can be found in
  3. // the LICENSE file.
  4. //
  5. // Package excelize providing a set of functions that allow you to write to and
  6. // read from XLAM / XLSM / XLSX / XLTM / XLTX files. Supports reading and
  7. // writing spreadsheet documents generated by Microsoft Excel™ 2007 and later.
  8. // Supports complex components by high compatibility, and provided streaming
  9. // API for generating or reading data from a worksheet with huge amounts of
  10. // data. This library needs Go version 1.16 or later.
  11. package excelize
  12. import (
  13. "fmt"
  14. "math"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "github.com/xuri/nfp"
  19. )
  20. // languageInfo defined the required fields of localization support for number format.
  21. type languageInfo struct {
  22. apFmt string
  23. tags []string
  24. localMonth func(t time.Time, abbr int) string
  25. }
  26. // numberFormat directly maps the number format parser runtime required
  27. // fields.
  28. type numberFormat struct {
  29. section []nfp.Section
  30. t time.Time
  31. sectionIdx int
  32. date1904, isNumeric, hours, seconds bool
  33. number float64
  34. ap, localCode, result, value, valueSectionType string
  35. }
  36. var (
  37. // supportedTokenTypes list the supported number format token types currently.
  38. supportedTokenTypes = []string{
  39. nfp.TokenSubTypeLanguageInfo,
  40. nfp.TokenTypeColor,
  41. nfp.TokenTypeCurrencyLanguage,
  42. nfp.TokenTypeDateTimes,
  43. nfp.TokenTypeElapsedDateTimes,
  44. nfp.TokenTypeGeneral,
  45. nfp.TokenTypeLiteral,
  46. nfp.TokenTypeTextPlaceHolder,
  47. nfp.TokenTypeZeroPlaceHolder,
  48. }
  49. // supportedLanguageInfo directly maps the supported language ID and tags.
  50. supportedLanguageInfo = map[string]languageInfo{
  51. "36": {tags: []string{"af"}, localMonth: localMonthsNameAfrikaans, apFmt: apFmtAfrikaans},
  52. "445": {tags: []string{"bn-IN"}, localMonth: localMonthsNameBangla, apFmt: nfp.AmPm[0]},
  53. "4": {tags: []string{"zh-Hans"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
  54. "7804": {tags: []string{"zh"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
  55. "804": {tags: []string{"zh-CN"}, localMonth: localMonthsNameChinese1, apFmt: nfp.AmPm[2]},
  56. "1004": {tags: []string{"zh-SG"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2]},
  57. "7C04": {tags: []string{"zh-Hant"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
  58. "C04": {tags: []string{"zh-HK"}, localMonth: localMonthsNameChinese2, apFmt: nfp.AmPm[2]},
  59. "1404": {tags: []string{"zh-MO"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
  60. "404": {tags: []string{"zh-TW"}, localMonth: localMonthsNameChinese3, apFmt: nfp.AmPm[2]},
  61. "9": {tags: []string{"en"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  62. "1000": {tags: []string{
  63. "aa", "aa-DJ", "aa-ER", "aa-ER", "aa-NA", "agq", "agq-CM", "ak", "ak-GH", "sq-ML",
  64. "gsw-LI", "gsw-CH", "ar-TD", "ar-KM", "ar-DJ", "ar-ER", "ar-IL", "ar-MR", "ar-PS",
  65. "ar-SO", "ar-SS", "ar-SD", "ar-001", "ast", "ast-ES", "asa", "asa-TZ", "ksf", "ksf-CM",
  66. "bm", "bm-Latn-ML", "bas", "bas-CM", "bem", "bem-ZM", "bez", "bez-TZ", "byn", "byn-ER",
  67. "brx", "brx-IN", "ca-AD", "ca-FR", "ca-IT", "ceb", "ceb-Latn", "ceb-Latn-PH", "tzm-Latn-MA",
  68. "ccp", "ccp-Cakm", "ccp-Cakm-BD", "ccp-Cakm-IN", "ce-RU", "cgg", "cgg-UG", "cu-RU", "swc",
  69. "swc-CD", "kw", "ke-GB", "da-GL", "dua", "dua-CM", "nl-AW", "nl-BQ", "nl-CW", "nl-SX",
  70. "nl-SR", "dz", "ebu", "ebu-KE", "en-AS", "en-AI", "en-AG", "en-AT", "en-BS", "en-BB",
  71. "en-BE", "en-BM", "en-BW", "en-IO", "en-VG", "en-BI", "en-CM", "en-KY", "en-CX", "en-CC",
  72. "en-CK", "en-CY", "en-DK", "en-DM", "en-ER", "en-150", "en-FK", "en-FI", "en-FJ", "en-GM",
  73. "en-DE", "en-GH", "en-GI", "en-GD", "en-GU", "en-GG", "en-GY", "en-IM", "en-IL", "en-JE",
  74. "en-KE", "en-KI", "en-LS", "en-LR", "en-MO", "en-MG", "en-MW", "en-MT", "en-MH", "en-MU",
  75. "en-FM", "en-MS", "en-NA", "en-NR", "en-NL", "en-NG", "en-NU", "en-NF", "en-MP", "en-PK",
  76. "en-PW", "en-PG", "en-PN", "en-PR", "en-RW", "en-KN", "en-LC", "en-VC", "en-WS", "en-SC",
  77. "en-SL", "en-SX", "en-SI", "en-SB", "en-SS", "en-SH", "en-SD", "en-SZ", "en-SE", "en-CH",
  78. "en-TZ", "en-TK", "en-TO", "en-TC", "en-TV", "en-UG", "en-UM", "en-VI", "en-VU", "en-001",
  79. "en-ZM", "eo", "eo-001", "ee", "ee-GH", "ee-TG", "ewo", "ewo-CM", "fo-DK", "fr-DZ",
  80. "fr-BJ", "fr-BF", "fr-BI", "fr-CF", "fr-TD", "fr-KM", "fr-CG", "fr-DJ", "fr-GQ", "fr-GF",
  81. "fr-PF", "fr-GA", "fr-GP", "fr-GN", "fr-MG", "fr-MQ", "fr-MR", "fr-MU", "fr-YT", "fr-NC",
  82. "fr-NE", "fr-RW", "fr-BL", "fr-MF", "fr-PM", "fr-SC", "fr-SY", "fr-TG", "fr-TN", "fr-VU",
  83. "fr-WF", "fur", "fur-IT", "ff-Latn-BF", "ff-CM", "ff-Latn-CM", "ff-Latn-GM", "ff-Latn-GH",
  84. "ff-GN", "ff-Latn-GN", "ff-Latn-GW", "ff-Latn-LR", "ff-MR", "ff-Latn-MR", "ff-Latn-NE",
  85. "ff-Latn-SL", "lg", "lg-UG", "de-BE", "de-IT", "el-CY", "guz", "guz-KE", "ha-Latn-GH",
  86. "ha-Latn-NG", "ia-FR", "ia-001", "it-SM", "it-VA", "jv", "jv-Latn", "jv-Latn-ID", "dyo",
  87. "dyo-SN", "kea", "kea-CV", "kab", "kab-DZ", "kkj", "kkj-CM", "kln", "kln-KE", "kam",
  88. "kam-KE", "ks-Arab-IN", "ki", "ki-KE", "sw-TZ", "sw-UG", "ko-KP", "khq", "khq-ML", "ses",
  89. "ses-ML", "nmg", "nmq-CM", "ku-Arab-IR", "lkt", "lkt-US", "lag", "lag-TZ", "ln", "ln-AO",
  90. "ln-CF", "ln-CD", "nds", "nds-DE", "nds-NL", "lu", "lu-CD", "luo", "luo", "luo-KE", "luy",
  91. "luy-KE", "jmc", "jmc-TZ", "mgh", "mgh-MZ", "kde", "kde-TZ", "mg", "mg-MG", "gv", "gv-IM",
  92. "mas", "mas-KE", "mas-TZ", "mas-IR", "mer", "mer-KE", "mgo", "mgo-CM", "mfe", "mfe-MU",
  93. "mua", "mua-CM", "nqo", "nqo-GN", "nqa", "naq-NA", "nnh", "nnh-CM", "jgo", "jgo-CM",
  94. "lrc-IQ", "lrc-IR", "nd", "nd-ZW", "nb-SJ", "nus", "nus-SD", "nus-SS", "nyn", "nyn-UG",
  95. "om-KE", "os", "os-GE", "os-RU", "ps-PK", "fa-AF", "pt-AO", "pt-CV", "pt-GQ", "pt-GW",
  96. "pt-LU", "pt-MO", "pt-MZ", "pt-ST", "pt-CH", "pt-TL", "prg-001", "ksh", "ksh-DE", "rof",
  97. "rof-TZ", "rn", "rn-BI", "ru-BY", "ru-KZ", "ru-KG", "ru-UA", "rwk", "rwk-TZ", "ssy",
  98. "ssy-ER", "saq", "saq-KE", "sg", "sq-CF", "sbp", "sbp-TZ", "seh", "seh-MZ", "ksb", "ksb-TZ",
  99. "sn", "sn-Latn", "sn-Latn-ZW", "xog", "xog-UG", "so-DJ", "so-ET", "so-KE", "nr", "nr-ZA",
  100. "st-LS", "es-BZ", "es-BR", "es-PH", "zgh", "zgh-Tfng-MA", "zgh-Tfng", "ss", "ss-ZA",
  101. "ss-SZ", "sv-AX", "shi", "shi-Tfng", "shi-Tfng-MA", "shi-Latn", "shi-Latn-MA", "dav",
  102. "dav-KE", "ta-MY", "ta-SG", "twq", "twq-NE", "teo", "teo-KE", "teo-UG", "bo-IN", "tig",
  103. "tig-ER", "to", "to-TO", "tr-CY", "uz-Arab", "us-Arab-AF", "vai", "vai-Vaii",
  104. "vai-Vaii-LR", "vai-Latn-LR", "vai-Latn", "vo", "vo-001", "vun", "vun-TZ", "wae",
  105. "wae-CH", "wal", "wae-ET", "yav", "yav-CM", "yo-BJ", "dje", "dje-NE",
  106. }, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  107. "C09": {tags: []string{"en-AU"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
  108. "2829": {tags: []string{"en-BZ"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  109. "1009": {tags: []string{"en-CA"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  110. "2409": {tags: []string{"en-029"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  111. "3C09": {tags: []string{"en-HK"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  112. "4009": {tags: []string{"en-IN"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  113. "1809": {tags: []string{"en-IE"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
  114. "2009": {tags: []string{"en-JM"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  115. "4409": {tags: []string{"en-MY"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  116. "1409": {tags: []string{"en-NZ"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  117. "3409": {tags: []string{"en-PH"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  118. "4809": {tags: []string{"en-SG"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  119. "1C09": {tags: []string{"en-ZA"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  120. "2C09": {tags: []string{"en-TT"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  121. "4C09": {tags: []string{"en-AE"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  122. "809": {tags: []string{"en-GB"}, localMonth: localMonthsNameEnglish, apFmt: strings.ToLower(nfp.AmPm[0])},
  123. "409": {tags: []string{"en-US"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  124. "3009": {tags: []string{"en-ZW"}, localMonth: localMonthsNameEnglish, apFmt: nfp.AmPm[0]},
  125. "C": {tags: []string{"fr"}, localMonth: localMonthsNameFrench, apFmt: nfp.AmPm[0]},
  126. "7": {tags: []string{"de"}, localMonth: localMonthsNameGerman, apFmt: nfp.AmPm[0]},
  127. "C07": {tags: []string{"de-AT"}, localMonth: localMonthsNameAustria, apFmt: nfp.AmPm[0]},
  128. "407": {tags: []string{"de-DE"}, localMonth: localMonthsNameGerman, apFmt: nfp.AmPm[0]},
  129. "3C": {tags: []string{"ga"}, localMonth: localMonthsNameIrish, apFmt: apFmtIrish},
  130. "83C": {tags: []string{"ga-IE"}, localMonth: localMonthsNameIrish, apFmt: apFmtIrish},
  131. "10": {tags: []string{"it"}, localMonth: localMonthsNameItalian, apFmt: nfp.AmPm[0]},
  132. "11": {tags: []string{"ja"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese},
  133. "411": {tags: []string{"ja-JP"}, localMonth: localMonthsNameChinese3, apFmt: apFmtJapanese},
  134. "12": {tags: []string{"ko"}, localMonth: localMonthsNameKorean, apFmt: apFmtKorean},
  135. "412": {tags: []string{"ko-KR"}, localMonth: localMonthsNameKorean, apFmt: apFmtKorean},
  136. "7C50": {tags: []string{"mn-Mong"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
  137. "850": {tags: []string{"mn-Mong-CN"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
  138. "C50": {tags: []string{"mn-Mong-MN"}, localMonth: localMonthsNameTraditionalMongolian, apFmt: nfp.AmPm[0]},
  139. "19": {tags: []string{"ru"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
  140. "819": {tags: []string{"ru-MD"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
  141. "419": {tags: []string{"ru-RU"}, localMonth: localMonthsNameRussian, apFmt: nfp.AmPm[0]},
  142. "A": {tags: []string{"es"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  143. "2C0A": {tags: []string{"es-AR"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  144. "200A": {tags: []string{"es-VE"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  145. "400A": {tags: []string{"es-BO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  146. "340A": {tags: []string{"es-CL"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  147. "240A": {tags: []string{"es-CO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  148. "140A": {tags: []string{"es-CR"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  149. "5C0A": {tags: []string{"es-CU"}, localMonth: localMonthsNameSpanish, apFmt: apFmtCuba},
  150. "1C0A": {tags: []string{"es-DO"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  151. "300A": {tags: []string{"es-EC"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  152. "440A": {tags: []string{"es-SV"}, localMonth: localMonthsNameSpanish, apFmt: apFmtSpanish},
  153. "1E": {tags: []string{"th"}, localMonth: localMonthsNameThai, apFmt: nfp.AmPm[0]},
  154. "41E": {tags: []string{"th-TH"}, localMonth: localMonthsNameThai, apFmt: nfp.AmPm[0]},
  155. "51": {tags: []string{"bo"}, localMonth: localMonthsNameTibetan, apFmt: apFmtTibetan},
  156. "451": {tags: []string{"bo-CN"}, localMonth: localMonthsNameTibetan, apFmt: apFmtTibetan},
  157. "1F": {tags: []string{"tr"}, localMonth: localMonthsNameTurkish, apFmt: apFmtTurkish},
  158. "41F": {tags: []string{"tr-TR"}, localMonth: localMonthsNameTurkish, apFmt: apFmtTurkish},
  159. "52": {tags: []string{"cy"}, localMonth: localMonthsNameWelsh, apFmt: apFmtWelsh},
  160. "452": {tags: []string{"cy-GB"}, localMonth: localMonthsNameWelsh, apFmt: apFmtWelsh},
  161. "2A": {tags: []string{"vi"}, localMonth: localMonthsNameVietnamese, apFmt: apFmtVietnamese},
  162. "42A": {tags: []string{"vi-VN"}, localMonth: localMonthsNameVietnamese, apFmt: apFmtVietnamese},
  163. "88": {tags: []string{"wo"}, localMonth: localMonthsNameWolof, apFmt: apFmtWolof},
  164. "488": {tags: []string{"wo-SN"}, localMonth: localMonthsNameWolof, apFmt: apFmtWolof},
  165. "34": {tags: []string{"xh"}, localMonth: localMonthsNameXhosa, apFmt: nfp.AmPm[0]},
  166. "434": {tags: []string{"xh-ZA"}, localMonth: localMonthsNameXhosa, apFmt: nfp.AmPm[0]},
  167. "78": {tags: []string{"ii"}, localMonth: localMonthsNameYi, apFmt: apFmtYi},
  168. "478": {tags: []string{"ii-CN"}, localMonth: localMonthsNameYi, apFmt: apFmtYi},
  169. "35": {tags: []string{"zu"}, localMonth: localMonthsNameZulu, apFmt: nfp.AmPm[0]},
  170. "435": {tags: []string{"zu-ZA"}, localMonth: localMonthsNameZulu, apFmt: nfp.AmPm[0]},
  171. }
  172. // monthNamesBangla list the month names in the Bangla.
  173. monthNamesBangla = []string{
  174. "\u099C\u09BE\u09A8\u09C1\u09AF\u09BC\u09BE\u09B0\u09C0",
  175. "\u09AB\u09C7\u09AC\u09CD\u09B0\u09C1\u09AF\u09BC\u09BE\u09B0\u09C0",
  176. "\u09AE\u09BE\u09B0\u09CD\u099A",
  177. "\u098F\u09AA\u09CD\u09B0\u09BF\u09B2",
  178. "\u09AE\u09C7",
  179. "\u099C\u09C1\u09A8",
  180. "\u099C\u09C1\u09B2\u09BE\u0987",
  181. "\u0986\u0997\u09B8\u09CD\u099F",
  182. "\u09B8\u09C7\u09AA\u09CD\u099F\u09C7\u09AE\u09CD\u09AC\u09B0",
  183. "\u0985\u0995\u09CD\u099F\u09CB\u09AC\u09B0",
  184. "\u09A8\u09AD\u09C7\u09AE\u09CD\u09AC\u09B0",
  185. "\u09A1\u09BF\u09B8\u09C7\u09AE\u09CD\u09AC\u09B0",
  186. }
  187. // monthNamesAfrikaans list the month names in the Afrikaans.
  188. monthNamesAfrikaans = []string{"Januarie", "Februarie", "Maart", "April", "Mei", "Junie", "Julie", "Augustus", "September", "Oktober", "November", "Desember"}
  189. // monthNamesAfrikaansAbbr lists the month name abbreviations in Afrikaans
  190. monthNamesAfrikaansAbbr = []string{"Jan.", "Feb.", "Maa.", "Apr.", "Mei", "Jun.", "Jul.", "Aug.", "Sep.", "Okt.", "Nov.", "Des."}
  191. // monthNamesChinese list the month names in the Chinese.
  192. monthNamesChinese = []string{"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"}
  193. // monthNamesChineseAbbr1 list the month number and character abbreviation in Chinese
  194. monthNamesChineseAbbrPlus = []string{"0月", "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月"}
  195. // monthNamesChinesePlus list the month names in Chinese plus the character 月
  196. monthNamesChinesePlus = []string{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"}
  197. // monthNamesKoreanAbbrPlus lists out the month number plus 월 for the Korean language
  198. monthNamesKoreanAbbrPlus = []string{"0월", "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월"}
  199. // monthNamesTradMongolian lists the month number for use with traditional Mongolian
  200. monthNamesTradMongolian = []string{"M01", "M02", "M03", "M04", "M05", "M06", "M07", "M08", "M09", "M10", "M11", "M12"}
  201. // monthNamesFrench list the month names in the French.
  202. monthNamesFrench = []string{"janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"}
  203. // monthNamesFrenchAbbr lists the month name abbreviations in French
  204. monthNamesFrenchAbbr = []string{"janv.", "févr.", "mars", "avri.", "mai", "juin", "juil.", "août", "sept.", "octo.", "nove.", "déce."}
  205. // monthNamesGerman list the month names in the German.
  206. monthNamesGerman = []string{"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
  207. // monthNamesGermanAbbr list the month abbreviations in German
  208. monthNamesGermanAbbr = []string{"Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"}
  209. // monthNamesAustria list the month names in the Austria.
  210. monthNamesAustria = []string{"Jänner", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
  211. // monthNamesAustriaAbbr list the month name abbreviations in Austrian
  212. monthNamesAustriaAbbr = []string{"Jän", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"}
  213. // monthNamesIrish list the month names in the Irish.
  214. monthNamesIrish = []string{"Eanáir", "Feabhra", "Márta", "Aibreán", "Bealtaine", "Meitheamh", "Iúil", "Lúnasa", "Meán Fómhair", "Deireadh Fómhair", "Samhain", "Nollaig"}
  215. // monthNamesIrishAbbr lists the month abbreviations in Irish
  216. monthNamesIrishAbbr = []string{"Ean", "Feabh", "Márta", "Aib", "Beal", "Meith", "Iúil", "Lún", "MFómh", "DFómh", "Samh", "Noll"}
  217. // monthNamesItalian list the month names in the Italian.
  218. monthNamesItalian = []string{"gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"}
  219. // monthNamesItalianAbbr list the month name abbreviations in Italian
  220. monthNamesItalianAbbr = []string{"gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic"}
  221. // monthNamesRussian list the month names in the Russian.
  222. monthNamesRussian = []string{"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"}
  223. // monthNamesRussianAbbr list the month abbreviations for Russian.
  224. monthNamesRussianAbbr = []string{"янв.", "фев.", "март", "апр.", "май", "июнь", "июль", "авг.", "сен.", "окт.", "ноя.", "дек."}
  225. // monthNamesSpanish list the month names in the Spanish.
  226. monthNamesSpanish = []string{"enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"}
  227. // monthNamesSpanishAbbr list the month abbreviations in Spanish
  228. monthNamesSpanishAbbr = []string{"ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"}
  229. // monthNamesThai list the month names in the Thai.
  230. monthNamesThai = []string{
  231. "\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21",
  232. "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c",
  233. "\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21",
  234. "\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19",
  235. "\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21",
  236. "\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19",
  237. "\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21",
  238. "\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21",
  239. "\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19",
  240. "\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21",
  241. "\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19",
  242. "\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21",
  243. }
  244. // monthNamesTibetan list the month names in the Tibetan.
  245. monthNamesTibetan = []string{
  246. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f44\u0f0b\u0f54\u0f7c\u0f0b",
  247. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
  248. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f42\u0f66\u0f74\u0f58\u0f0b\u0f54\u0f0b",
  249. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f5e\u0f72\u0f0b\u0f54\u0f0b",
  250. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f63\u0f94\u0f0b\u0f54\u0f0b",
  251. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0fb2\u0f74\u0f42\u0f0b\u0f54\u0f0b",
  252. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f51\u0f74\u0f53\u0f0b\u0f54\u0f0b",
  253. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f62\u0f92\u0fb1\u0f51\u0f0b\u0f54\u0f0b",
  254. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f51\u0f42\u0f74\u0f0b\u0f54\u0f0b",
  255. "\u0f66\u0fa4\u0fb1\u0f72\u0f0b\u0f5f\u0fb3\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f54\u0f0d",
  256. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f45\u0f72\u0f42\u0f0b\u0f54\u0f0b",
  257. "\u0f5f\u0fb3\u0f0b\u0f56\u0f0b\u0f56\u0f45\u0f74\u0f0b\u0f42\u0f49\u0f72\u0f66\u0f0b\u0f54\u0f0b",
  258. }
  259. // monthNamesTibetanAbbr lists the month name abbreviations in Tibetan
  260. monthNamesTibetanAbbr = []string{
  261. "\u0f5f\u0fb3\u0f0b\u0f21",
  262. "\u0f5f\u0fb3\u0f0b\u0f22",
  263. "\u0f5f\u0fb3\u0f0b\u0f23",
  264. "\u0f5f\u0fb3\u0f0b\u0f24",
  265. "\u0f5f\u0fb3\u0f0b\u0f25",
  266. "\u0f5f\u0fb3\u0f0b\u0f26",
  267. "\u0f5f\u0fb3\u0f0b\u0f27",
  268. "\u0f5f\u0fb3\u0f0b\u0f28",
  269. "\u0f5f\u0fb3\u0f0b\u0f29",
  270. "\u0f5f\u0fb3\u0f0b\u0f21\u0f20",
  271. "\u0f5f\u0fb3\u0f0b\u0f21\u0f21",
  272. "\u0f5f\u0fb3\u0f0b\u0f21\u0f22",
  273. }
  274. // monthNamesTurkish list the month names in the Turkish.
  275. monthNamesTurkish = []string{"Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"}
  276. // monthNamesTurkishAbbr lists the month name abbreviations in Turkish, this prevents string concatenation
  277. monthNamesTurkishAbbr = []string{"Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara"}
  278. // monthNamesVietnamese list the month name used for Vietnamese
  279. monthNamesVietnamese = []string{"Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"}
  280. // monthNamesVietnameseAbbr3 list the mid-form abbreviation for Vietnamese months
  281. monthNamesVietnameseAbbr3 = []string{"Thg 1", "Thg 2", "Thg 3", "Thg 4", "Thg 5", "Thg 6", "Thg 7", "Thg 8", "Thg 9", "Thg 10", "Thg 11", "Thg 12"}
  282. // monthNamesVietnameseAbbr5 list the short-form abbreviation for Vietnamese months
  283. monthNamesVietnameseAbbr5 = []string{"T 1", "T 2", "T 3", "T 4", "T 5", "T 6", "T 7", "T 8", "T 9", "T 10", "T 11", "T 12"}
  284. // monthNamesWelsh list the month names in the Welsh.
  285. monthNamesWelsh = []string{"Ionawr", "Chwefror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorffennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"}
  286. // monthNamesWelshAbbr lists the month name abbreviations in Welsh, this prevents string concatenation
  287. monthNamesWelshAbbr = []string{"Ion", "Chwef", "Maw", "Ebr", "Mai", "Meh", "Gorff", "Awst", "Medi", "Hyd", "Tach", "Rhag"}
  288. // monthNamesWolof list the month names in the Wolof.
  289. monthNamesWolof = []string{"Samwiye", "Fewriye", "Maars", "Awril", "Me", "Suwe", "Sullet", "Ut", "Septàmbar", "Oktoobar", "Noowàmbar", "Desàmbar"}
  290. // monthNamesWolofAbbr list the month name abbreviations in Wolof, this prevents string concatenation
  291. monthNamesWolofAbbr = []string{"Sam.", "Few.", "Maa", "Awr.", "Me", "Suw", "Sul.", "Ut", "Sept.", "Okt.", "Now.", "Des."}
  292. // monthNamesXhosa list the month names in the Xhosa.
  293. monthNamesXhosa = []string{"uJanuwari", "uFebuwari", "uMatshi", "uAprili", "uMeyi", "uJuni", "uJulayi", "uAgasti", "uSeptemba", "uOktobha", "uNovemba", "uDisemba"}
  294. // monthNamesXhosaAbbr list the month abbreviations in the Xhosa, this prevents string concatenation
  295. monthNamesXhosaAbbr = []string{"uJan.", "uFeb.", "uMat.", "uEpr.", "uMey.", "uJun.", "uJul.", "uAg.", "uSep.", "uOkt.", "uNov.", "uDis."}
  296. // monthNamesYi list the month names in the Yi.
  297. monthNamesYi = []string{"\ua2cd", "\ua44d", "\ua315", "\ua1d6", "\ua26c", "\ua0d8", "\ua3c3", "\ua246", "\ua22c", "\ua2b0", "\ua2b0\ua2aa", "\ua2b0\ua44b"}
  298. // monthNamesYiSuffix lists the month names in Yi with the "\ua1aa" suffix
  299. monthNamesYiSuffix = []string{"\ua2cd\ua1aa", "\ua44d\ua1aa", "\ua315\ua1aa", "\ua1d6\ua1aa", "\ua26c\ua1aa", "\ua0d8\ua1aa", "\ua3c3\ua1aa", "\ua246\ua1aa", "\ua22c\ua1aa", "\ua2b0\ua1aa", "\ua2b0\ua2aa\ua1aa", "\ua2b0\ua44b\ua1aa"}
  300. // monthNamesZulu list the month names in the Zulu.
  301. monthNamesZulu = []string{"Januwari", "Febhuwari", "Mashi", "Ephreli", "Meyi", "Juni", "Julayi", "Agasti", "Septemba", "Okthoba", "Novemba", "Disemba"}
  302. // monthNamesZuluAbbr list the month name abbreviations in Zulu
  303. monthNamesZuluAbbr = []string{"Jan", "Feb", "Mas", "Eph", "Mey", "Jun", "Jul", "Agas", "Sep", "Okt", "Nov", "Dis"}
  304. // apFmtAfrikaans defined the AM/PM name in the Afrikaans.
  305. apFmtAfrikaans = "vm./nm."
  306. // apFmtCuba defined the AM/PM name in the Cuba.
  307. apFmtCuba = "a.m./p.m."
  308. // apFmtIrish defined the AM/PM name in the Irish.
  309. apFmtIrish = "r.n./i.n."
  310. // apFmtJapanese defined the AM/PM name in the Japanese.
  311. apFmtJapanese = "午前/午後"
  312. // apFmtKorean defined the AM/PM name in the Korean.
  313. apFmtKorean = "오전/오후"
  314. // apFmtSpanish defined the AM/PM name in the Spanish.
  315. apFmtSpanish = "a. m./p. m."
  316. // apFmtTibetan defined the AM/PM name in the Tibetan.
  317. apFmtTibetan = "\u0f66\u0f94\u0f0b\u0f51\u0fb2\u0f7c\u0f0b/\u0f55\u0fb1\u0f72\u0f0b\u0f51\u0fb2\u0f7c\u0f0b"
  318. // apFmtTurkish defined the AM/PM name in the Turkish.
  319. apFmtTurkish = "\u00F6\u00F6/\u00F6\u0053"
  320. // apFmtVietnamese defined the AM/PM name in the Vietnamese.
  321. apFmtVietnamese = "SA/CH"
  322. // apFmtWolof defined the AM/PM name in the Wolof.
  323. apFmtWolof = "Sub/Ngo"
  324. // apFmtYi defined the AM/PM name in the Yi.
  325. apFmtYi = "\ua3b8\ua111/\ua06f\ua2d2"
  326. // apFmtWelsh defined the AM/PM name in the Welsh.
  327. apFmtWelsh = "yb/yh"
  328. )
  329. // prepareNumberic split the number into two before and after parts by a
  330. // decimal point.
  331. func (nf *numberFormat) prepareNumberic(value string) {
  332. if nf.isNumeric, _, _ = isNumeric(value); !nf.isNumeric {
  333. return
  334. }
  335. }
  336. // format provides a function to return a string parse by number format
  337. // expression. If the given number format is not supported, this will return
  338. // the original cell value.
  339. func format(value, numFmt string, date1904 bool) string {
  340. p := nfp.NumberFormatParser()
  341. nf := numberFormat{section: p.Parse(numFmt), value: value, date1904: date1904}
  342. nf.number, nf.valueSectionType = nf.getValueSectionType(value)
  343. nf.prepareNumberic(value)
  344. for i, section := range nf.section {
  345. nf.sectionIdx = i
  346. if section.Type != nf.valueSectionType {
  347. continue
  348. }
  349. if nf.isNumeric {
  350. switch section.Type {
  351. case nfp.TokenSectionPositive:
  352. return nf.positiveHandler()
  353. case nfp.TokenSectionNegative:
  354. return nf.negativeHandler()
  355. default:
  356. return nf.zeroHandler()
  357. }
  358. }
  359. return nf.textHandler()
  360. }
  361. return value
  362. }
  363. // positiveHandler will be handling positive selection for a number format
  364. // expression.
  365. func (nf *numberFormat) positiveHandler() (result string) {
  366. nf.t, nf.hours, nf.seconds = timeFromExcelTime(nf.number, nf.date1904), false, false
  367. for i, token := range nf.section[nf.sectionIdx].Items {
  368. if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral {
  369. result = nf.value
  370. return
  371. }
  372. if token.TType == nfp.TokenTypeCurrencyLanguage {
  373. if err := nf.currencyLanguageHandler(i, token); err != nil {
  374. result = nf.value
  375. return
  376. }
  377. }
  378. if token.TType == nfp.TokenTypeDateTimes {
  379. nf.dateTimesHandler(i, token)
  380. }
  381. if token.TType == nfp.TokenTypeElapsedDateTimes {
  382. nf.elapsedDateTimesHandler(token)
  383. }
  384. if token.TType == nfp.TokenTypeLiteral {
  385. nf.result += token.TValue
  386. continue
  387. }
  388. if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == strings.Repeat("0", len(token.TValue)) {
  389. if isNum, precision, decimal := isNumeric(nf.value); isNum {
  390. if nf.number < 1 {
  391. nf.result += "0"
  392. continue
  393. }
  394. if precision > 15 {
  395. nf.result += strconv.FormatFloat(decimal, 'f', -1, 64)
  396. } else {
  397. nf.result += fmt.Sprintf("%.f", nf.number)
  398. }
  399. continue
  400. }
  401. }
  402. }
  403. result = nf.result
  404. return
  405. }
  406. // currencyLanguageHandler will be handling currency and language types tokens for a number
  407. // format expression.
  408. func (nf *numberFormat) currencyLanguageHandler(i int, token nfp.Token) (err error) {
  409. for _, part := range token.Parts {
  410. if inStrSlice(supportedTokenTypes, part.Token.TType, true) == -1 {
  411. err = ErrUnsupportedNumberFormat
  412. return
  413. }
  414. if _, ok := supportedLanguageInfo[strings.ToUpper(part.Token.TValue)]; !ok {
  415. err = ErrUnsupportedNumberFormat
  416. return
  417. }
  418. nf.localCode = strings.ToUpper(part.Token.TValue)
  419. }
  420. return
  421. }
  422. // localAmPm return AM/PM name by supported language ID.
  423. func (nf *numberFormat) localAmPm(ap string) string {
  424. if languageInfo, ok := supportedLanguageInfo[nf.localCode]; ok {
  425. return languageInfo.apFmt
  426. }
  427. return ap
  428. }
  429. // localMonthsNameEnglish returns the English name of the month.
  430. func localMonthsNameEnglish(t time.Time, abbr int) string {
  431. if abbr == 3 {
  432. return t.Month().String()[:3]
  433. }
  434. if abbr == 4 {
  435. return t.Month().String()
  436. }
  437. return t.Month().String()[:1]
  438. }
  439. // localMonthsNameAfrikaans returns the Afrikaans name of the month.
  440. func localMonthsNameAfrikaans(t time.Time, abbr int) string {
  441. if abbr == 3 {
  442. return monthNamesAfrikaansAbbr[int(t.Month())-1]
  443. }
  444. if abbr == 4 {
  445. return monthNamesAfrikaans[int(t.Month())-1]
  446. }
  447. return monthNamesAfrikaansAbbr[int(t.Month())-1][:1]
  448. }
  449. // localMonthsNameAustria returns the Austria name of the month.
  450. func localMonthsNameAustria(t time.Time, abbr int) string {
  451. if abbr == 3 {
  452. return monthNamesAustriaAbbr[int(t.Month())-1]
  453. }
  454. if abbr == 4 {
  455. return monthNamesAustria[int(t.Month())-1]
  456. }
  457. return monthNamesAustriaAbbr[int(t.Month())-1][:1]
  458. }
  459. // localMonthsNameBangla returns the German name of the month.
  460. func localMonthsNameBangla(t time.Time, abbr int) string {
  461. if abbr == 3 || abbr == 4 {
  462. return monthNamesBangla[int(t.Month())-1]
  463. }
  464. return string([]rune(monthNamesBangla[int(t.Month())-1])[:1])
  465. }
  466. // localMonthsNameFrench returns the French name of the month.
  467. func localMonthsNameFrench(t time.Time, abbr int) string {
  468. if abbr == 3 {
  469. month := monthNamesFrench[int(t.Month())-1]
  470. if len([]rune(month)) <= 4 {
  471. return monthNamesFrench[int(t.Month())-1]
  472. }
  473. return monthNamesFrenchAbbr[int(t.Month())-1]
  474. }
  475. if abbr == 4 {
  476. return monthNamesFrench[int(t.Month())-1]
  477. }
  478. return monthNamesFrenchAbbr[int(t.Month())-1][:1]
  479. }
  480. // localMonthsNameIrish returns the Irish name of the month.
  481. func localMonthsNameIrish(t time.Time, abbr int) string {
  482. if abbr == 3 {
  483. return monthNamesIrishAbbr[int(t.Month()-1)]
  484. }
  485. if abbr == 4 {
  486. return monthNamesIrish[int(t.Month())-1]
  487. }
  488. return monthNamesIrishAbbr[int(t.Month())-1][:1]
  489. }
  490. // localMonthsNameItalian returns the Italian name of the month.
  491. func localMonthsNameItalian(t time.Time, abbr int) string {
  492. if abbr == 3 {
  493. return monthNamesItalianAbbr[int(t.Month())-1]
  494. }
  495. if abbr == 4 {
  496. return monthNamesItalian[int(t.Month())-1]
  497. }
  498. return monthNamesItalianAbbr[int(t.Month())-1][:1]
  499. }
  500. // localMonthsNameGerman returns the German name of the month.
  501. func localMonthsNameGerman(t time.Time, abbr int) string {
  502. if abbr == 3 {
  503. return monthNamesGermanAbbr[int(t.Month())-1]
  504. }
  505. if abbr == 4 {
  506. return monthNamesGerman[int(t.Month())-1]
  507. }
  508. return monthNamesGermanAbbr[int(t.Month())-1][:1]
  509. }
  510. // localMonthsNameChinese1 returns the Chinese name of the month.
  511. func localMonthsNameChinese1(t time.Time, abbr int) string {
  512. if abbr == 3 {
  513. return monthNamesChineseAbbrPlus[int(t.Month())]
  514. }
  515. if abbr == 4 {
  516. return monthNamesChinesePlus[int(t.Month())-1]
  517. }
  518. return monthNamesChinese[int(t.Month())-1]
  519. }
  520. // localMonthsNameChinese2 returns the Chinese name of the month.
  521. func localMonthsNameChinese2(t time.Time, abbr int) string {
  522. if abbr == 3 || abbr == 4 {
  523. return monthNamesChinesePlus[int(t.Month())-1]
  524. }
  525. return monthNamesChinese[int(t.Month())-1]
  526. }
  527. // localMonthsNameChinese3 returns the Chinese name of the month.
  528. func localMonthsNameChinese3(t time.Time, abbr int) string {
  529. if abbr == 3 || abbr == 4 {
  530. return monthNamesChineseAbbrPlus[int(t.Month())]
  531. }
  532. return strconv.Itoa(int(t.Month()))
  533. }
  534. // localMonthsNameKorean returns the Korean name of the month.
  535. func localMonthsNameKorean(t time.Time, abbr int) string {
  536. if abbr == 3 || abbr == 4 {
  537. return monthNamesKoreanAbbrPlus[int(t.Month())]
  538. }
  539. return strconv.Itoa(int(t.Month()))
  540. }
  541. // localMonthsNameTraditionalMongolian returns the Traditional Mongolian name of the month.
  542. func localMonthsNameTraditionalMongolian(t time.Time, abbr int) string {
  543. if abbr == 5 {
  544. return "M"
  545. }
  546. return monthNamesTradMongolian[int(t.Month()-1)]
  547. }
  548. // localMonthsNameRussian returns the Russian name of the month.
  549. func localMonthsNameRussian(t time.Time, abbr int) string {
  550. if abbr == 3 {
  551. month := monthNamesRussian[int(t.Month())-1]
  552. if len([]rune(month)) <= 4 {
  553. return month
  554. }
  555. return monthNamesRussianAbbr[int(t.Month())-1]
  556. }
  557. if abbr == 4 {
  558. return monthNamesRussian[int(t.Month())-1]
  559. }
  560. return string([]rune(monthNamesRussian[int(t.Month())-1])[:1])
  561. }
  562. // localMonthsNameSpanish returns the Spanish name of the month.
  563. func localMonthsNameSpanish(t time.Time, abbr int) string {
  564. if abbr == 3 {
  565. return monthNamesSpanishAbbr[int(t.Month())-1]
  566. }
  567. if abbr == 4 {
  568. return monthNamesSpanish[int(t.Month())-1]
  569. }
  570. return monthNamesSpanishAbbr[int(t.Month())-1][:1]
  571. }
  572. // localMonthsNameThai returns the Thai name of the month.
  573. func localMonthsNameThai(t time.Time, abbr int) string {
  574. if abbr == 3 {
  575. r := []rune(monthNamesThai[int(t.Month())-1])
  576. return string(r[:1]) + "." + string(r[len(r)-2:len(r)-1]) + "."
  577. }
  578. if abbr == 4 {
  579. return monthNamesThai[int(t.Month())-1]
  580. }
  581. return string([]rune(monthNamesThai[int(t.Month())-1])[:1])
  582. }
  583. // localMonthsNameTibetan returns the Tibetan name of the month.
  584. func localMonthsNameTibetan(t time.Time, abbr int) string {
  585. if abbr == 3 {
  586. return monthNamesTibetanAbbr[int(t.Month())-1]
  587. }
  588. if abbr == 5 {
  589. if t.Month() == 10 {
  590. return "\u0f66"
  591. }
  592. return "\u0f5f"
  593. }
  594. return monthNamesTibetan[int(t.Month())-1]
  595. }
  596. // localMonthsNameTurkish returns the Turkish name of the month.
  597. func localMonthsNameTurkish(t time.Time, abbr int) string {
  598. if abbr == 3 {
  599. return monthNamesTurkishAbbr[int(t.Month())-1]
  600. }
  601. if abbr == 4 {
  602. return monthNamesTurkish[int(t.Month())-1]
  603. }
  604. return string([]rune(monthNamesTurkishAbbr[int(t.Month())-1])[:1])
  605. }
  606. // localMonthsNameWelsh returns the Welsh name of the month.
  607. func localMonthsNameWelsh(t time.Time, abbr int) string {
  608. if abbr == 3 {
  609. return monthNamesWelshAbbr[int(t.Month())-1]
  610. }
  611. if abbr == 4 {
  612. return monthNamesWelsh[int(t.Month())-1]
  613. }
  614. return monthNamesWelshAbbr[int(t.Month())-1][:1]
  615. }
  616. // localMonthsNameVietnamese returns the Vietnamese name of the month.
  617. func localMonthsNameVietnamese(t time.Time, abbr int) string {
  618. if abbr == 3 {
  619. return monthNamesVietnameseAbbr3[int(t.Month()-1)]
  620. }
  621. if abbr == 5 {
  622. return monthNamesVietnameseAbbr5[int(t.Month()-1)]
  623. }
  624. return monthNamesVietnamese[int(t.Month()-1)]
  625. }
  626. // localMonthsNameWolof returns the Wolof name of the month.
  627. func localMonthsNameWolof(t time.Time, abbr int) string {
  628. if abbr == 3 {
  629. return monthNamesWolofAbbr[int(t.Month())-1]
  630. }
  631. if abbr == 4 {
  632. return monthNamesWolof[int(t.Month())-1]
  633. }
  634. return monthNamesWolof[int(t.Month())-1][:1]
  635. }
  636. // localMonthsNameXhosa returns the Xhosa name of the month.
  637. func localMonthsNameXhosa(t time.Time, abbr int) string {
  638. if abbr == 3 {
  639. return monthNamesXhosaAbbr[int(t.Month())-1]
  640. }
  641. if abbr == 4 {
  642. return monthNamesXhosa[int(t.Month())-1]
  643. }
  644. return "u"
  645. }
  646. // localMonthsNameYi returns the Yi name of the month.
  647. func localMonthsNameYi(t time.Time, abbr int) string {
  648. if abbr == 3 || abbr == 4 {
  649. return monthNamesYiSuffix[int(t.Month()-1)]
  650. }
  651. return string([]rune(monthNamesYi[int(t.Month())-1])[:1])
  652. }
  653. // localMonthsNameZulu returns the Zulu name of the month.
  654. func localMonthsNameZulu(t time.Time, abbr int) string {
  655. if abbr == 3 {
  656. return monthNamesZuluAbbr[int(t.Month()-1)]
  657. }
  658. if abbr == 4 {
  659. return monthNamesZulu[int(t.Month())-1]
  660. }
  661. return monthNamesZuluAbbr[int(t.Month())-1][:1]
  662. }
  663. // localMonthName return months name by supported language ID.
  664. func (nf *numberFormat) localMonthsName(abbr int) string {
  665. if languageInfo, ok := supportedLanguageInfo[nf.localCode]; ok {
  666. return languageInfo.localMonth(nf.t, abbr)
  667. }
  668. return localMonthsNameEnglish(nf.t, abbr)
  669. }
  670. // dateTimesHandler will be handling date and times types tokens for a number
  671. // format expression.
  672. func (nf *numberFormat) dateTimesHandler(i int, token nfp.Token) {
  673. if idx := inStrSlice(nfp.AmPm, strings.ToUpper(token.TValue), false); idx != -1 {
  674. if nf.ap == "" {
  675. nextHours := nf.hoursNext(i)
  676. aps := strings.Split(nf.localAmPm(token.TValue), "/")
  677. nf.ap = aps[0]
  678. if nextHours >= 12 {
  679. nf.ap = aps[1]
  680. }
  681. }
  682. nf.result += nf.ap
  683. return
  684. }
  685. if strings.Contains(strings.ToUpper(token.TValue), "M") {
  686. l := len(token.TValue)
  687. if l == 1 && !nf.hours && !nf.secondsNext(i) {
  688. nf.result += strconv.Itoa(int(nf.t.Month()))
  689. return
  690. }
  691. if l == 2 && !nf.hours && !nf.secondsNext(i) {
  692. nf.result += fmt.Sprintf("%02d", int(nf.t.Month()))
  693. return
  694. }
  695. if l == 3 {
  696. nf.result += nf.localMonthsName(3)
  697. return
  698. }
  699. if l == 4 || l > 5 {
  700. nf.result += nf.localMonthsName(4)
  701. return
  702. }
  703. if l == 5 {
  704. nf.result += nf.localMonthsName(5)
  705. return
  706. }
  707. }
  708. nf.yearsHandler(i, token)
  709. nf.daysHandler(i, token)
  710. nf.hoursHandler(i, token)
  711. nf.minutesHandler(token)
  712. nf.secondsHandler(token)
  713. }
  714. // yearsHandler will be handling years in the date and times types tokens for a
  715. // number format expression.
  716. func (nf *numberFormat) yearsHandler(i int, token nfp.Token) {
  717. years := strings.Contains(strings.ToUpper(token.TValue), "Y")
  718. if years && len(token.TValue) <= 2 {
  719. nf.result += strconv.Itoa(nf.t.Year())[2:]
  720. return
  721. }
  722. if years && len(token.TValue) > 2 {
  723. nf.result += strconv.Itoa(nf.t.Year())
  724. return
  725. }
  726. }
  727. // daysHandler will be handling days in the date and times types tokens for a
  728. // number format expression.
  729. func (nf *numberFormat) daysHandler(i int, token nfp.Token) {
  730. if strings.Contains(strings.ToUpper(token.TValue), "D") {
  731. switch len(token.TValue) {
  732. case 1:
  733. nf.result += strconv.Itoa(nf.t.Day())
  734. return
  735. case 2:
  736. nf.result += fmt.Sprintf("%02d", nf.t.Day())
  737. return
  738. case 3:
  739. nf.result += nf.t.Weekday().String()[:3]
  740. return
  741. default:
  742. nf.result += nf.t.Weekday().String()
  743. return
  744. }
  745. }
  746. }
  747. // hoursHandler will be handling hours in the date and times types tokens for a
  748. // number format expression.
  749. func (nf *numberFormat) hoursHandler(i int, token nfp.Token) {
  750. nf.hours = strings.Contains(strings.ToUpper(token.TValue), "H")
  751. if nf.hours {
  752. h := nf.t.Hour()
  753. ap, ok := nf.apNext(i)
  754. if ok {
  755. nf.ap = ap[0]
  756. if h >= 12 {
  757. nf.ap = ap[1]
  758. }
  759. if h > 12 {
  760. h -= 12
  761. }
  762. }
  763. if nf.ap != "" && nf.hoursNext(i) == -1 && h > 12 {
  764. h -= 12
  765. }
  766. switch len(token.TValue) {
  767. case 1:
  768. nf.result += strconv.Itoa(h)
  769. return
  770. default:
  771. nf.result += fmt.Sprintf("%02d", h)
  772. return
  773. }
  774. }
  775. }
  776. // minutesHandler will be handling minutes in the date and times types tokens
  777. // for a number format expression.
  778. func (nf *numberFormat) minutesHandler(token nfp.Token) {
  779. if strings.Contains(strings.ToUpper(token.TValue), "M") {
  780. nf.hours = false
  781. switch len(token.TValue) {
  782. case 1:
  783. nf.result += strconv.Itoa(nf.t.Minute())
  784. return
  785. default:
  786. nf.result += fmt.Sprintf("%02d", nf.t.Minute())
  787. return
  788. }
  789. }
  790. }
  791. // secondsHandler will be handling seconds in the date and times types tokens
  792. // for a number format expression.
  793. func (nf *numberFormat) secondsHandler(token nfp.Token) {
  794. nf.seconds = strings.Contains(strings.ToUpper(token.TValue), "S")
  795. if nf.seconds {
  796. switch len(token.TValue) {
  797. case 1:
  798. nf.result += strconv.Itoa(nf.t.Second())
  799. return
  800. default:
  801. nf.result += fmt.Sprintf("%02d", nf.t.Second())
  802. return
  803. }
  804. }
  805. }
  806. // elapsedDateTimesHandler will be handling elapsed date and times types tokens
  807. // for a number format expression.
  808. func (nf *numberFormat) elapsedDateTimesHandler(token nfp.Token) {
  809. if strings.Contains(strings.ToUpper(token.TValue), "H") {
  810. nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Hours())
  811. return
  812. }
  813. if strings.Contains(strings.ToUpper(token.TValue), "M") {
  814. nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Minutes())
  815. return
  816. }
  817. if strings.Contains(strings.ToUpper(token.TValue), "S") {
  818. nf.result += fmt.Sprintf("%.f", nf.t.Sub(excel1900Epoc).Seconds())
  819. return
  820. }
  821. }
  822. // hoursNext detects if a token of type hours exists after a given tokens list.
  823. func (nf *numberFormat) hoursNext(i int) int {
  824. tokens := nf.section[nf.sectionIdx].Items
  825. for idx := i + 1; idx < len(tokens); idx++ {
  826. if tokens[idx].TType == nfp.TokenTypeDateTimes {
  827. if strings.Contains(strings.ToUpper(tokens[idx].TValue), "H") {
  828. t := timeFromExcelTime(nf.number, false)
  829. return t.Hour()
  830. }
  831. }
  832. }
  833. return -1
  834. }
  835. // apNext detects if a token of type AM/PM exists after a given tokens list.
  836. func (nf *numberFormat) apNext(i int) ([]string, bool) {
  837. tokens := nf.section[nf.sectionIdx].Items
  838. for idx := i + 1; idx < len(tokens); idx++ {
  839. if tokens[idx].TType == nfp.TokenTypeDateTimes {
  840. if strings.Contains(strings.ToUpper(tokens[idx].TValue), "H") {
  841. return nil, false
  842. }
  843. if i := inStrSlice(nfp.AmPm, tokens[idx].TValue, false); i != -1 {
  844. return strings.Split(nf.localAmPm(tokens[idx].TValue), "/"), true
  845. }
  846. }
  847. }
  848. return nil, false
  849. }
  850. // secondsNext detects if a token of type seconds exists after a given tokens
  851. // list.
  852. func (nf *numberFormat) secondsNext(i int) bool {
  853. tokens := nf.section[nf.sectionIdx].Items
  854. for idx := i + 1; idx < len(tokens); idx++ {
  855. if tokens[idx].TType == nfp.TokenTypeDateTimes {
  856. return strings.Contains(strings.ToUpper(tokens[idx].TValue), "S")
  857. }
  858. }
  859. return false
  860. }
  861. // negativeHandler will be handling negative selection for a number format
  862. // expression.
  863. func (nf *numberFormat) negativeHandler() (result string) {
  864. for _, token := range nf.section[nf.sectionIdx].Items {
  865. if inStrSlice(supportedTokenTypes, token.TType, true) == -1 || token.TType == nfp.TokenTypeGeneral {
  866. result = nf.value
  867. return
  868. }
  869. if token.TType == nfp.TokenTypeLiteral {
  870. nf.result += token.TValue
  871. continue
  872. }
  873. if token.TType == nfp.TokenTypeZeroPlaceHolder && token.TValue == strings.Repeat("0", len(token.TValue)) {
  874. if isNum, precision, decimal := isNumeric(nf.value); isNum {
  875. if math.Abs(nf.number) < 1 {
  876. nf.result += "0"
  877. continue
  878. }
  879. if precision > 15 {
  880. nf.result += strings.TrimLeft(strconv.FormatFloat(decimal, 'f', -1, 64), "-")
  881. } else {
  882. nf.result += fmt.Sprintf("%.f", math.Abs(nf.number))
  883. }
  884. continue
  885. }
  886. }
  887. }
  888. result = nf.result
  889. return
  890. }
  891. // zeroHandler will be handling zero selection for a number format expression.
  892. func (nf *numberFormat) zeroHandler() string {
  893. return nf.value
  894. }
  895. // textHandler will be handling text selection for a number format expression.
  896. func (nf *numberFormat) textHandler() (result string) {
  897. for _, token := range nf.section[nf.sectionIdx].Items {
  898. if token.TType == nfp.TokenTypeLiteral {
  899. result += token.TValue
  900. }
  901. if token.TType == nfp.TokenTypeTextPlaceHolder {
  902. result += nf.value
  903. }
  904. }
  905. return result
  906. }
  907. // getValueSectionType returns its applicable number format expression section
  908. // based on the given value.
  909. func (nf *numberFormat) getValueSectionType(value string) (float64, string) {
  910. isNum, _, _ := isNumeric(value)
  911. if !isNum {
  912. return 0, nfp.TokenSectionText
  913. }
  914. number, _ := strconv.ParseFloat(value, 64)
  915. if number > 0 {
  916. return number, nfp.TokenSectionPositive
  917. }
  918. if number < 0 {
  919. return number, nfp.TokenSectionNegative
  920. }
  921. return number, nfp.TokenSectionZero
  922. }