currency.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:generate go run gen.go gen_common.go -output tables.go
  5. // Package currency contains currency-related functionality.
  6. //
  7. // NOTE: the formatting functionality is currently under development and may
  8. // change without notice.
  9. package currency // import "golang.org/x/text/currency"
  10. import (
  11. "errors"
  12. "sort"
  13. "golang.org/x/text/internal/tag"
  14. "golang.org/x/text/language"
  15. )
  16. // TODO:
  17. // - language-specific currency names.
  18. // - currency formatting.
  19. // - currency information per region
  20. // - register currency code (there are no private use area)
  21. // TODO: remove Currency type from package language.
  22. // Kind determines the rounding and rendering properties of a currency value.
  23. type Kind struct {
  24. rounding rounding
  25. // TODO: formatting type: standard, accounting. See CLDR.
  26. }
  27. type rounding byte
  28. const (
  29. standard rounding = iota
  30. cash
  31. )
  32. var (
  33. // Standard defines standard rounding and formatting for currencies.
  34. Standard Kind = Kind{rounding: standard}
  35. // Cash defines rounding and formatting standards for cash transactions.
  36. Cash Kind = Kind{rounding: cash}
  37. // Accounting defines rounding and formatting standards for accounting.
  38. Accounting Kind = Kind{rounding: standard}
  39. )
  40. // Rounding reports the rounding characteristics for the given currency, where
  41. // scale is the number of fractional decimals and increment is the number of
  42. // units in terms of 10^(-scale) to which to round to.
  43. func (k Kind) Rounding(cur Unit) (scale, increment int) {
  44. info := currency.Elem(int(cur.index))[3]
  45. switch k.rounding {
  46. case standard:
  47. info &= roundMask
  48. case cash:
  49. info >>= cashShift
  50. }
  51. return int(roundings[info].scale), int(roundings[info].increment)
  52. }
  53. // Unit is an ISO 4217 currency designator.
  54. type Unit struct {
  55. index uint16
  56. }
  57. // String returns the ISO code of u.
  58. func (u Unit) String() string {
  59. if u.index == 0 {
  60. return "XXX"
  61. }
  62. return currency.Elem(int(u.index))[:3]
  63. }
  64. // Amount creates an Amount for the given currency unit and amount.
  65. func (u Unit) Amount(amount interface{}) Amount {
  66. // TODO: verify amount is a supported number type
  67. return Amount{amount: amount, currency: u}
  68. }
  69. var (
  70. errSyntax = errors.New("currency: tag is not well-formed")
  71. errValue = errors.New("currency: tag is not a recognized currency")
  72. )
  73. // ParseISO parses a 3-letter ISO 4217 currency code. It returns an error if s
  74. // is not well-formed or not a recognized currency code.
  75. func ParseISO(s string) (Unit, error) {
  76. var buf [4]byte // Take one byte more to detect oversize keys.
  77. key := buf[:copy(buf[:], s)]
  78. if !tag.FixCase("XXX", key) {
  79. return Unit{}, errSyntax
  80. }
  81. if i := currency.Index(key); i >= 0 {
  82. if i == xxx {
  83. return Unit{}, nil
  84. }
  85. return Unit{uint16(i)}, nil
  86. }
  87. return Unit{}, errValue
  88. }
  89. // MustParseISO is like ParseISO, but panics if the given currency unit
  90. // cannot be parsed. It simplifies safe initialization of Unit values.
  91. func MustParseISO(s string) Unit {
  92. c, err := ParseISO(s)
  93. if err != nil {
  94. panic(err)
  95. }
  96. return c
  97. }
  98. // FromRegion reports the currency unit that is currently legal tender in the
  99. // given region according to CLDR. It will return false if region currently does
  100. // not have a legal tender.
  101. func FromRegion(r language.Region) (currency Unit, ok bool) {
  102. x := regionToCode(r)
  103. i := sort.Search(len(regionToCurrency), func(i int) bool {
  104. return regionToCurrency[i].region >= x
  105. })
  106. if i < len(regionToCurrency) && regionToCurrency[i].region == x {
  107. return Unit{regionToCurrency[i].code}, true
  108. }
  109. return Unit{}, false
  110. }
  111. // FromTag reports the most likely currency for the given tag. It considers the
  112. // currency defined in the -u extension and infers the region if necessary.
  113. func FromTag(t language.Tag) (Unit, language.Confidence) {
  114. if cur := t.TypeForKey("cu"); len(cur) == 3 {
  115. c, _ := ParseISO(cur)
  116. return c, language.Exact
  117. }
  118. r, conf := t.Region()
  119. if cur, ok := FromRegion(r); ok {
  120. return cur, conf
  121. }
  122. return Unit{}, language.No
  123. }
  124. var (
  125. // Undefined and testing.
  126. XXX Unit = Unit{}
  127. XTS Unit = Unit{xts}
  128. // G10 currencies https://en.wikipedia.org/wiki/G10_currencies.
  129. USD Unit = Unit{usd}
  130. EUR Unit = Unit{eur}
  131. JPY Unit = Unit{jpy}
  132. GBP Unit = Unit{gbp}
  133. CHF Unit = Unit{chf}
  134. AUD Unit = Unit{aud}
  135. NZD Unit = Unit{nzd}
  136. CAD Unit = Unit{cad}
  137. SEK Unit = Unit{sek}
  138. NOK Unit = Unit{nok}
  139. // Additional common currencies as defined by CLDR.
  140. BRL Unit = Unit{brl}
  141. CNY Unit = Unit{cny}
  142. DKK Unit = Unit{dkk}
  143. INR Unit = Unit{inr}
  144. RUB Unit = Unit{rub}
  145. HKD Unit = Unit{hkd}
  146. IDR Unit = Unit{idr}
  147. KRW Unit = Unit{krw}
  148. MXN Unit = Unit{mxn}
  149. PLN Unit = Unit{pln}
  150. SAR Unit = Unit{sar}
  151. THB Unit = Unit{thb}
  152. TRY Unit = Unit{try}
  153. TWD Unit = Unit{twd}
  154. ZAR Unit = Unit{zar}
  155. // Precious metals.
  156. XAG Unit = Unit{xag}
  157. XAU Unit = Unit{xau}
  158. XPT Unit = Unit{xpt}
  159. XPD Unit = Unit{xpd}
  160. )