summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yastrebov <yastrebov.alex@gmail.com>2021-10-18 14:56:52 +0000
committerIan Lance Taylor <iant@golang.org>2021-11-05 21:09:21 +0000
commit459fa287ae002e3df243c0bd10ea915f5c64f687 (patch)
tree31310ae64844e922b5b1ca44c8dcbbe006f81f06
parent85a1c56496a61b2c4e607faaf3369d473cf2589d (diff)
downloadgolang-x-text-459fa287ae002e3df243c0bd10ea915f5c64f687.tar.gz
text/currency: format currency amount according to the locale
Fixes golang/go#47623 Change-Id: Ie6be9db93bf58f597f1ea4d864fcb507235b1018 GitHub-Last-Rev: 4c8f3557daf5440390c0775ed6e71ec80f8c11e8 GitHub-Pull-Request: golang/text#27 Reviewed-on: https://go-review.googlesource.com/c/text/+/353935 Reviewed-by: Marcel van Lohuizen <mpvl@golang.org> Trust: Marcel van Lohuizen <mpvl@golang.org> Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
-rw-r--r--currency/format.go36
-rw-r--r--currency/format_test.go23
2 files changed, 41 insertions, 18 deletions
diff --git a/currency/format.go b/currency/format.go
index 1115263..cc4570d 100644
--- a/currency/format.go
+++ b/currency/format.go
@@ -6,11 +6,13 @@ package currency
import (
"fmt"
- "io"
"sort"
"golang.org/x/text/internal/format"
"golang.org/x/text/internal/language/compact"
+ "golang.org/x/text/internal/number"
+
+ "golang.org/x/text/language"
)
// Amount is an amount-currency unit pair.
@@ -34,8 +36,6 @@ func (a Amount) Currency() Unit { return a.currency }
//
// Add/Sub/Div/Mul/Round.
-var space = []byte(" ")
-
// Format implements fmt.Formatter. It accepts format.State for
// language-specific rendering.
func (a Amount) Format(s fmt.State, verb rune) {
@@ -58,9 +58,11 @@ type formattedValue struct {
// Format implements fmt.Formatter. It accepts format.State for
// language-specific rendering.
func (v formattedValue) Format(s fmt.State, verb rune) {
+ var tag language.Tag
var lang compact.ID
if state, ok := s.(format.State); ok {
- lang, _ = compact.RegionalID(compact.Tag(state.Language()))
+ tag = state.Language()
+ lang, _ = compact.RegionalID(compact.Tag(tag))
}
// Get the options. Use DefaultFormat if not present.
@@ -73,18 +75,22 @@ func (v formattedValue) Format(s fmt.State, verb rune) {
cur = opt.currency
}
- // TODO: use pattern.
- io.WriteString(s, opt.symbol(lang, cur))
+ sym := opt.symbol(lang, cur)
if v.amount != nil {
- s.Write(space)
-
- // TODO: apply currency-specific rounding
- scale, _ := opt.kind.Rounding(cur)
- if _, ok := s.Precision(); !ok {
- fmt.Fprintf(s, "%.*f", scale, v.amount)
- } else {
- fmt.Fprint(s, v.amount)
- }
+ var f number.Formatter
+ f.InitDecimal(tag)
+
+ scale, increment := opt.kind.Rounding(cur)
+ f.RoundingContext.SetScale(scale)
+ f.RoundingContext.Increment = uint32(increment)
+ f.RoundingContext.IncrementScale = uint8(scale)
+ f.RoundingContext.Mode = number.ToNearestAway
+
+ d := f.Append(nil, v.amount)
+
+ fmt.Fprint(s, sym, " ", string(d))
+ } else {
+ fmt.Fprint(s, sym)
}
}
diff --git a/currency/format_test.go b/currency/format_test.go
index 0aa0d58..5cb11eb 100644
--- a/currency/format_test.go
+++ b/currency/format_test.go
@@ -12,8 +12,10 @@ import (
)
var (
+ de = language.German
en = language.English
fr = language.French
+ de_CH = language.MustParse("de-CH")
en_US = language.AmericanEnglish
en_GB = language.BritishEnglish
en_AU = language.MustParse("en-AU")
@@ -42,20 +44,35 @@ func TestFormatting(t *testing.T) {
9: {en, 9.0, Symbol.Default(EUR), "€ 9.00"},
10: {en, 10.123, Symbol.Default(KRW), "₩ 10"},
- 11: {fr, 11.52, Symbol.Default(TWD), "TWD 11.52"},
+ 11: {fr, 11.52, Symbol.Default(TWD), "TWD 11,52"},
12: {en, 12.123, Symbol.Default(czk), "CZK 12.12"},
13: {en, 13.123, Symbol.Default(czk).Kind(Cash), "CZK 13"},
14: {en, 14.12345, ISO.Default(MustParseISO("CLF")), "CLF 14.1235"},
15: {en, USD.Amount(15.00), ISO.Default(TWD), "USD 15.00"},
16: {en, KRW.Amount(16.00), ISO.Kind(Cash), "KRW 16"},
- // TODO: support integers as well.
-
17: {en, USD, nil, "USD"},
18: {en, USD, ISO, "USD"},
19: {en, USD, Symbol, "$"},
20: {en_GB, USD, Symbol, "US$"},
21: {en_AU, USD, NarrowSymbol, "$"},
+
+ // https://en.wikipedia.org/wiki/Decimal_separator
+ 22: {de, EUR.Amount(1234567.89), nil, "EUR 1.234.567,89"},
+ 23: {fr, EUR.Amount(1234567.89), nil, "EUR 1\u00a0234\u00a0567,89"},
+ 24: {en_AU, EUR.Amount(1234567.89), nil, "EUR 1,234,567.89"},
+ 25: {de_CH, EUR.Amount(1234567.89), nil, "EUR 1’234’567.89"},
+
+ // https://en.wikipedia.org/wiki/Cash_rounding
+ 26: {de, NOK.Amount(2.49), ISO.Kind(Cash), "NOK 2"},
+ 27: {de, NOK.Amount(2.50), ISO.Kind(Cash), "NOK 3"},
+ 28: {de, DKK.Amount(0.24), ISO.Kind(Cash), "DKK 0,00"},
+ 29: {de, DKK.Amount(0.25), ISO.Kind(Cash), "DKK 0,50"},
+
+ // integers
+ 30: {de, EUR.Amount(1234567), nil, "EUR 1.234.567,00"},
+ 31: {en, CNY.Amount(0), NarrowSymbol, "¥ 0.00"},
+ 32: {en, CNY.Amount(0), Symbol, "CN¥ 0.00"},
}
for i, tc := range testCases {
p := message.NewPrinter(tc.tag)