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