// 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. package currency import ( "errors" "sort" "gx/QmVgdgtv5rUcWWcHvHN1vdGkXi8UNztJ7JuT72YUJgG2ic/go-text/internal/tag" "gx/QmVgdgtv5rUcWWcHvHN1vdGkXi8UNztJ7JuT72YUJgG2ic/go-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(c Currency) (scale, increment int) { info := currency.Elem(int(c.index))[3] switch k.rounding { case standard: info &= roundMask case cash: info >>= cashShift } return int(roundings[info].scale), int(roundings[info].increment) } // Currency is an ISO 4217 currency designator. type Currency struct { index uint16 } // String returns the ISO code of c. func (c Currency) String() string { if c.index == 0 { return "XXX" } return currency.Elem(int(c.index))[:3] } // Value creates a Value for the given currency and amount. func (c Currency) Value(amount interface{}) Value { // TODO: verify amount is a supported number type return Value{amount: amount, currency: c} } 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 code. It returns an error if s not // well-formed or not a recognized currency code. func ParseISO(s string) (Currency, error) { var buf [4]byte // Take one byte more to detect oversize keys. key := buf[:copy(buf[:], s)] if !tag.FixCase("XXX", key) { return Currency{}, errSyntax } if i := currency.Index(key); i >= 0 { return Currency{uint16(i)}, nil } return Currency{}, errValue } // MustParseISO is like ParseISO, but panics if the given currency // cannot be parsed. It simplifies safe initialization of Currency values. func MustParseISO(s string) Currency { c, err := ParseISO(s) if err != nil { panic(err) } return c } // FromRegion reports the Currency 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) (tender Currency, 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 Currency{regionToCurrency[i].code}, true } return Currency{0}, 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) (Currency, language.Confidence) { if cur := t.TypeForKey("cu"); len(cur) == 3 { var buf [3]byte copy(buf[:], cur) tag.FixCase("XXX", buf[:]) if x := currency.Index(buf[:]); x > 0 { return Currency{uint16(x)}, language.Exact } } r, conf := t.Region() if cur, ok := FromRegion(r); ok { return cur, conf } return Currency{}, language.No } var ( // Undefined and testing. XXX Currency = Currency{xxx} XTS Currency = Currency{xts} // G10 currencies https://en.wikipedia.org/wiki/G10_currencies. USD Currency = Currency{usd} EUR Currency = Currency{eur} JPY Currency = Currency{jpy} GBP Currency = Currency{gbp} CHF Currency = Currency{chf} AUD Currency = Currency{aud} NZD Currency = Currency{nzd} CAD Currency = Currency{cad} SEK Currency = Currency{sek} NOK Currency = Currency{nok} // Additional common currencies as defined by CLDR. BRL Currency = Currency{brl} CNY Currency = Currency{cny} DKK Currency = Currency{dkk} INR Currency = Currency{inr} RUB Currency = Currency{rub} HKD Currency = Currency{hkd} IDR Currency = Currency{idr} KRW Currency = Currency{krw} MXN Currency = Currency{mxn} PLN Currency = Currency{pln} SAR Currency = Currency{sar} THB Currency = Currency{thb} TRY Currency = Currency{try} TWD Currency = Currency{twd} ZAR Currency = Currency{zar} // Precious metals. XAG Currency = Currency{xag} XAU Currency = Currency{xau} XPT Currency = Currency{xpt} XPD Currency = Currency{xpd} )