123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- // 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}
- )
|