如何在 JavaScript 中使用货币和语言环境来格式化大数字(由字符串表示)?

Ric*_*cký 8 javascript locale bigdecimal number-formatting currency-formatting

我正在开发一个用 TypeScript 编写的银行应用程序前端。

从后端,我收到:

  • 字符串中保留 2 位小数的金额(例如帐户余额)。这可能是一个很大的值 - 小数点前超过 15 位。
    • 其格式为:"32012012012012312.09"
  • 货币代码字符串(例如"USD"

我想使用千位分隔符、货币符号和 NBSP/NNBSP 处理来格式化金额,所有这些都与提供的区域设置有关。最简单的方法是什么?

对于部分问题是否有潜在的解决方案?例如 1. 格式化数字和 2. 格式化货币符号。

我尝试过的:

  • Intl.NumberFormat- 我喜欢它,但它需要一个number | bigint(虽然它不会因字符串而崩溃),但它在大十进制数时不再精确 - 例如它的格式32_012_012_012_012_312.0932,012,012,012,012,310.00- 我相信这是关于数字的 JavaScript 限制,这就是为什么我寻找处理字符串的东西
  • accounting-js-formatMoney具有字符串和数字的函数 - 结果相同,但缺少传递区域设置的功能
  • 寻找有关此主题的其他库和线程 - 我研究了一点 big/bignumber/decimal.js 和 numeric.js,还没有尝试过它们,但我相信它们是关于处理大数字,而不是格式化,甚至是基于区域设置格式化

Šim*_*rek 6

不确定它是否适用于所有语言/区域设置:

\n
const [main, decimal] = "32_012_012_012_012_312.09".split(".")\nconst mainNumber = BigInt(main.replaceAll(\'_\', \'\'))\nconst decimalNumber = Number.parseFloat(\'0.\' + decimal)\n\nconst start = mainNumber.toLocaleString(\'de-DE\') // "32.012.012.012.012.312"\nconst end = decimalNumber.toLocaleString(\'de-DE\', { style: \'currency\', currency: \'EUR\' }) // "0,09\xc2\xa0\xe2\x82\xac"\n\nconst result = start + end.substr(1) // "32.012.012.012.012.312,09\xc2\xa0\xe2\x82\xac"\n
Run Code Online (Sandbox Code Playgroud)\n


Ric*_*cký 5

使用\xc5\xa0imon Koc\xc3\xbarek\ 的建议单独格式化 BigInt 部分,并进一步以更Intl.NumberFormat安全的方式利用货币格式:

\n
const locale = \'de-DE\'\nconst currency = \'EUR\'\nconst amount = "321321321321321321.357" // parseFloat(c) gives 321321321321321340\n\n// in the comments I also give an example for \'321321321321321321.998\' because of rounding issue\nconst [mainString, decimalString] = amount.split(".") // [\'321321321321321321\', \'.357\' | \'998\']\n\nconst decimalFormat = new Intl.NumberFormat(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 })\nconst decimalFullString = `0.${decimalString}` // \'0.357\' | \'0.998\'\nconst decimalFullNumber = Number.parseFloat(decimalFullString) // 0.357 | 0.998\nconst decimalFullFinal = decimalFormat.format(decimalFullNumber) // \'0,36\' | \'1,00\'\nconst decimalFinal = decimalFullFinal.slice(1) // \',36\' | \',00\'\n\nconst mainFormat = new Intl.NumberFormat(locale, { minimumFractionDigits: 0 })\nlet mainBigInt = BigInt(mainString) // 321321321321321321n\nif (decimalFullFinal[0] === "1") mainBigInt += BigInt(1) // 321321321321321321n | 321321321321321322n\nconst mainFinal = mainFormat.format(mainBigInt) // \'321.321.321.321.321.321\' | \'321.321.321.321.321.322\'\n\nconst amountFinal = `${mainFinal}${decimalFinal}` // \'321.321.321.321.321.321,36\' | \'321.321.321.321.321.322,00\'\n\nconst currencyFormat = new Intl.NumberFormat(locale, { style: "currency", currency, maximumFractionDigits: 0 })\nconst template = currencyFormat.format(0) // \'\xe2\x82\xac0\'\nconst result = template.replace("0", amountFinal) // \'\xe2\x82\xac321.321.321.321.321.321,36\' | \'\xe2\x82\xac321.321.321.321.321.322,00\'\n
Run Code Online (Sandbox Code Playgroud)\n

运行:

\n
    \n
  • locale = \'fr\'产生\'321\xe2\x80\xaf321\xe2\x80\xaf321\xe2\x80\xaf321\xe2\x80\xaf321\xe2\x80\xaf321,36 \xe2\x82\xac\'(三重奏之间有 NNBSP)
  • \n
  • locale = \'de\'产生\'321.321.321.321.321.321,36 \xe2\x82\xac\'
  • \n
  • locale = \'en\'产生\'\xe2\x82\xac321,321,321,321,321,321.36\'
  • \n
\n

这也可以处理超过 2 位十进制数字的字符串数字。

\n