【问题标题】:Currency Format in Golang using currency.Symbol from golang.org/x/text/currencyGolang 中的货币格式使用来自 golang.org/x/text/currency 的 currency.Symbol
【发布时间】:2022-02-16 20:56:31
【问题描述】:

您好,我正在开发一个以货币格式化值的函数。我正在使用 golang.org/x/text/currency 来完成这项工作,但我得到的输出是逗号位置的点,没有千位分隔符。

func (produto *Produto) FormataPreco(valor int64) string {
    unit, _ := currency.ParseISO("BRL")
    p := message.NewPrinter(language.BrazilianPortuguese)
    return p.Sprint(currency.Symbol(unit.Amount(float64(valor) / 100)))
}

预期结果应该是 123.456,78 雷亚尔,但我得到的是 123456.78 雷亚尔

--- 编辑---

我做了一个使用硬编码值的版本,但我想要一个使用系统语言环境资源的解决方案。

func (produto *Produto) FormataPreco(valor int64) string {
    p := message.NewPrinter(language.BrazilianPortuguese)
    return p.Sprintf("R$ %.2f", float64(valor/100))
}

【问题讨论】:

  • 我在x/text/currency 的文档中没有看到任何迹象表明它以任何方式格式化数字分组。它按预期呈现货币符号,这就是它声称的作用。
  • 嗨@icza 我用这个解决方案做了一个版本。但我想要一个使用系统语言环境的。我确实使用了以下代码,其中货币是硬编码的 p := message.NewPrinter(language.BrazilianPortuguese) return p.Sprintf("R$ %.2f", float64(produto.Preco/100))

标签: go currency-formatting


【解决方案1】:

在这个例子中,我从语言代码中推断出货币格式。

https://goplay.space/#fqs9t8MG062

n := display.Tags(language.English)
for _, lcode := range []string{"en_US", "pt_BR", "de", "ja", "hi"} {
    lang := language.MustParse(lcode)
    cur, _ := currency.FromTag(lang)
    scale, _ := currency.Cash.Rounding(cur) // fractional digits
    dec := number.Decimal(100000.00, number.Scale(scale))
    p := message.NewPrinter(lang)
    p.Printf("%24v (%v): %v%v\n", n.Name(lang), cur, currency.Symbol(cur), dec)
}

//         American English (USD): $100,000.00
//     Brazilian Portuguese (BRL): R$100.000,00
//                   German (EUR): €100.000,00
//                 Japanese (JPY): ¥100,000
//                    Hindi (INR): ₹1,00,000.00

您还可以解析 ISO 货币代码,但您还必须指定格式化数字的语言。输出语言不会影响小数位数,但会影响逗号和句点的使用位置:

https://goplay.space/#DlxSmjZbHH6

for _, iso := range []string{"USD", "BRL", "EUR", "JPY", "INR"} {
    cur := currency.MustParseISO(iso)
    scale, _ := currency.Cash.Rounding(cur) // fractional digits
    dec := number.Decimal(100000.00, number.Scale(scale))
    p := message.NewPrinter(language.English)
    p.Printf("%v: %v%v\n", cur, currency.Symbol(cur), dec)
}

// USD: $100,000.00
// BRL: R$100,000.00
// EUR: €100,000.00
// JPY: ¥100,000
// INR: ₹100,000.00

某些货币以增量四舍五入,例如 0.05 或 0.50。对于这些情况,currency.Cash.Rounding(cur) 的第二个返回值将返回 5 或 50 而不是 1。要为 Decimal 格式化程序提供它所期望的 IncrementString,我们必须进行更多处理:

package main

import (
    "math"
    "strconv"

    "golang.org/x/text/currency"
    "golang.org/x/text/language"
    "golang.org/x/text/language/display"
    "golang.org/x/text/message"
    "golang.org/x/text/number"
)

func main() {
    n := display.Tags(language.English)
    for _, lcode := range []string{"en_US", "en_CA", "da", "ja"} {
        lang := language.MustParse(lcode)
        cur, _ := currency.FromTag(lang)
        scale, incCents := currency.Cash.Rounding(cur) // fractional digits
        incFloat := math.Pow10(-scale) * float64(incCents)
        incFmt := strconv.FormatFloat(incFloat, 'f', scale, 64)
        dec := number.Decimal(100000.26,
            number.Scale(scale), number.IncrementString(incFmt))
        p := message.NewPrinter(lang)
        p.Printf("%24v %v, %4s-rounding: %3v%v\n",
            n.Name(lang), cur, incFmt, currency.Symbol(cur), dec)
    }
}

//    American English USD, 0.01-rounding: $100,000.26
//    Canadian English CAD, 0.05-rounding: CA$100,000.25
//              Danish DKK, 0.50-rounding: DKK100.000,50
//            Japanese JPY,    1-rounding: ¥100,000

【讨论】:

    【解决方案2】:

    您可能会注意到,golang.org/x/text/currency 仍在进行中,并且有一段时间没有更新。

    注意:格式化功能目前正在开发中, 如有更改,恕不另行通知。

    如果您更喜欢使用简单的辅助函数来完成工作,您可以使用如下内容:

    func formatMoney(value int32, thousand, decimal string) string {
        var result string
        var isNegative bool
    
        if value < 0 {
            value = value * -1
            isNegative = true
        }
    
        // apply the decimal separator
        result = fmt.Sprintf("%s%02d%s", decimal, value%100, result)
        value /= 100
    
        // for each 3 dígits put a dot "."
        for value >= 1000 {
            result = fmt.Sprintf("%s%03d%s", thousand, value%1000, result)
            value /= 1000
        }
    
        if isNegative {
            return fmt.Sprintf("$ -%d%s", value, result)
        }
    
        return fmt.Sprintf("$ %d%s", value, result)
    }
    

    用法:

    formatMoney(10, ",", ".") // $ 0.10
    formatMoney(12345, ",", ".") // $ 123.45
    formatMoney(1234567, ",", ".") // $ 12,345.67
    formatMoney(-1234567, ",", ".") // $ -12,345.67
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 2010-09-24
      • 2018-04-01
      相关资源
      最近更新 更多