...

Source file src/golang.org/x/text/currency/currency.go

Documentation: golang.org/x/text/currency

     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  )
   186  

View as plain text