Estoy trabajando en el front-end de una aplicación bancaria escrito en TypeScript.
Desde el back-end, recibo:
"32012012012012312.09""USD" )Me gustaría formatear la cantidad con separadores de miles, un símbolo de moneda y manejo de NBSP/NNBSP, todo con respecto a la configuración regional proporcionada. ¿Cuál es la forma más fácil?
¿Existen posibles soluciones a los problemas parciales? Por ejemplo, 1. formatear el número y 2. formatear con el símbolo de moneda.
Lo que probé:
Intl.NumberFormat : me gusta, pero requiere un number | bigint (aunque no falla con las cadenas), pero deja de ser preciso en números decimales grandes, por ejemplo, formatea 32_012_012_012_012_312.09 como 32,012,012,012,012,310.00 . Creo que esto es una limitación de JavaScript con respecto a los números, por eso estoy buscando algo que lo maneje. instrumentos de cuerdaaccounting-js - función formatMoney con cadena y número - mismo resultado y falta la funcionalidad de pasar la configuración regional enNo estoy seguro si funciona para absolutamente todos los idiomas/locales:
const [main, decimal] = "32_012_012_012_012_312.09".split(".") const mainNumber = BigInt(main.replaceAll('_', '')) const decimalNumber = Number.parseFloat('0.' + decimal) const start = mainNumber.toLocaleString('de-DE') // "32.012.012.012.012.312" const end = decimalNumber.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' }) // "0,09 €" const result = start + end.substr(1) // "32.012.012.012.012.312,09 €"Usando el consejo de Šimon Kocúrek para formatear la parte BigInt por separado y llevarlo un paso más allá para seguir utilizando el formato de moneda de Intl.NumberFormat de una manera más segura:
const locale = 'de-DE' const currency = 'EUR' const amount = "321321321321321321.357" // parseFloat(c) gives 321321321321321340 // in the comments I also give an example for '321321321321321321.998' because of rounding issue const [mainString, decimalString] = amount.split(".") // ['321321321321321321', '.357' | '998'] const decimalFormat = new Intl.NumberFormat(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) const decimalFullString = `0.${decimalString}` // '0.357' | '0.998' const decimalFullNumber = Number.parseFloat(decimalFullString) // 0.357 | 0.998 const decimalFullFinal = decimalFormat.format(decimalFullNumber) // '0,36' | '1,00' const decimalFinal = decimalFullFinal.slice(1) // ',36' | ',00' const mainFormat = new Intl.NumberFormat(locale, { minimumFractionDigits: 0 }) let mainBigInt = BigInt(mainString) // 321321321321321321n if (decimalFullFinal[0] === "1") mainBigInt += BigInt(1) // 321321321321321321n | 321321321321321322n const mainFinal = mainFormat.format(mainBigInt) // '321.321.321.321.321.321' | '321.321.321.321.321.322' const amountFinal = `${mainFinal}${decimalFinal}` // '321.321.321.321.321.321,36' | '321.321.321.321.321.322,00' const currencyFormat = new Intl.NumberFormat(locale, { style: "currency", currency, maximumFractionDigits: 0 }) const template = currencyFormat.format(0) // '€0' const result = template.replace("0", amountFinal) // '€321.321.321.321.321.321,36' | '€321.321.321.321.321.322,00'Corriendo con:
locale = 'fr' produce '321 321 321 321 321 321,36 €' (con NNBSP entre tríos)locale = 'de' produce '321.321.321.321.321.321,36 €'locale = 'en' produce '€321,321,321,321,321,321.36'Esto también maneja números de cadena con más de 2 dígitos decimales.