| // Copyright 2015 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:generate go run gen.go gen_common.go -output tables.go |
| |
| // Package currency contains currency-related functionality. |
| // |
| // NOTE: the formatting functionality is currently under development and may |
| // change without notice. |
| package currency // import "golang.org/x/text/currency" |
| |
| import ( |
| "errors" |
| "sort" |
| |
| "golang.org/x/text/internal/tag" |
| "golang.org/x/text/language" |
| ) |
| |
| // TODO: |
| // - language-specific currency names. |
| // - currency formatting. |
| // - currency information per region |
| // - register currency code (there are no private use area) |
| |
| // TODO: remove Currency type from package language. |
| |
| // Kind determines the rounding and rendering properties of a currency value. |
| type Kind struct { |
| rounding rounding |
| // TODO: formatting type: standard, accounting. See CLDR. |
| } |
| |
| type rounding byte |
| |
| const ( |
| standard rounding = iota |
| cash |
| ) |
| |
| var ( |
| // Standard defines standard rounding and formatting for currencies. |
| Standard Kind = Kind{rounding: standard} |
| |
| // Cash defines rounding and formatting standards for cash transactions. |
| Cash Kind = Kind{rounding: cash} |
| |
| // Accounting defines rounding and formatting standards for accounting. |
| Accounting Kind = Kind{rounding: standard} |
| ) |
| |
| // Rounding reports the rounding characteristics for the given currency, where |
| // scale is the number of fractional decimals and increment is the number of |
| // units in terms of 10^(-scale) to which to round to. |
| func (k Kind) Rounding(cur Unit) (scale, increment int) { |
| info := currency.Elem(int(cur.index))[3] |
| switch k.rounding { |
| case standard: |
| info &= roundMask |
| case cash: |
| info >>= cashShift |
| } |
| return int(roundings[info].scale), int(roundings[info].increment) |
| } |
| |
| // Unit is an ISO 4217 currency designator. |
| type Unit struct { |
| index uint16 |
| } |
| |
| // String returns the ISO code of u. |
| func (u Unit) String() string { |
| if u.index == 0 { |
| return "XXX" |
| } |
| return currency.Elem(int(u.index))[:3] |
| } |
| |
| // Amount creates an Amount for the given currency unit and amount. |
| func (u Unit) Amount(amount interface{}) Amount { |
| // TODO: verify amount is a supported number type |
| return Amount{amount: amount, currency: u} |
| } |
| |
| var ( |
| errSyntax = errors.New("currency: tag is not well-formed") |
| errValue = errors.New("currency: tag is not a recognized currency") |
| ) |
| |
| // ParseISO parses a 3-letter ISO 4217 currency code. It returns an error if s |
| // is not well-formed or not a recognized currency code. |
| func ParseISO(s string) (Unit, error) { |
| var buf [4]byte // Take one byte more to detect oversize keys. |
| key := buf[:copy(buf[:], s)] |
| if !tag.FixCase("XXX", key) { |
| return Unit{}, errSyntax |
| } |
| if i := currency.Index(key); i >= 0 { |
| if i == xxx { |
| return Unit{}, nil |
| } |
| return Unit{uint16(i)}, nil |
| } |
| return Unit{}, errValue |
| } |
| |
| // MustParseISO is like ParseISO, but panics if the given currency unit |
| // cannot be parsed. It simplifies safe initialization of Unit values. |
| func MustParseISO(s string) Unit { |
| c, err := ParseISO(s) |
| if err != nil { |
| panic(err) |
| } |
| return c |
| } |
| |
| // FromRegion reports the currency unit that is currently legal tender in the |
| // given region according to CLDR. It will return false if region currently does |
| // not have a legal tender. |
| func FromRegion(r language.Region) (currency Unit, ok bool) { |
| x := regionToCode(r) |
| i := sort.Search(len(regionToCurrency), func(i int) bool { |
| return regionToCurrency[i].region >= x |
| }) |
| if i < len(regionToCurrency) && regionToCurrency[i].region == x { |
| return Unit{regionToCurrency[i].code}, true |
| } |
| return Unit{}, false |
| } |
| |
| // FromTag reports the most likely currency for the given tag. It considers the |
| // currency defined in the -u extension and infers the region if necessary. |
| func FromTag(t language.Tag) (Unit, language.Confidence) { |
| if cur := t.TypeForKey("cu"); len(cur) == 3 { |
| c, _ := ParseISO(cur) |
| return c, language.Exact |
| } |
| r, conf := t.Region() |
| if cur, ok := FromRegion(r); ok { |
| return cur, conf |
| } |
| return Unit{}, language.No |
| } |
| |
| var ( |
| // Undefined and testing. |
| XXX Unit = Unit{} |
| XTS Unit = Unit{xts} |
| |
| // G10 currencies https://en.wikipedia.org/wiki/G10_currencies. |
| USD Unit = Unit{usd} |
| EUR Unit = Unit{eur} |
| JPY Unit = Unit{jpy} |
| GBP Unit = Unit{gbp} |
| CHF Unit = Unit{chf} |
| AUD Unit = Unit{aud} |
| NZD Unit = Unit{nzd} |
| CAD Unit = Unit{cad} |
| SEK Unit = Unit{sek} |
| NOK Unit = Unit{nok} |
| |
| // Additional common currencies as defined by CLDR. |
| BRL Unit = Unit{brl} |
| CNY Unit = Unit{cny} |
| DKK Unit = Unit{dkk} |
| INR Unit = Unit{inr} |
| RUB Unit = Unit{rub} |
| HKD Unit = Unit{hkd} |
| IDR Unit = Unit{idr} |
| KRW Unit = Unit{krw} |
| MXN Unit = Unit{mxn} |
| PLN Unit = Unit{pln} |
| SAR Unit = Unit{sar} |
| THB Unit = Unit{thb} |
| TRY Unit = Unit{try} |
| TWD Unit = Unit{twd} |
| ZAR Unit = Unit{zar} |
| |
| // Precious metals. |
| XAG Unit = Unit{xag} |
| XAU Unit = Unit{xau} |
| XPT Unit = Unit{xpt} |
| XPD Unit = Unit{xpd} |
| ) |