JavaScript数字.toLocaleString去除货币符号

44

假设我们有

var number = 123456.789;

我希望以区域设置“de-DE”的方式显示这个数字

123.456,79

作为本地化为'ja-JP'

123,457

作为本地语言环境'en-US'

123,456.79

根据用户的语言环境,等等。问题在于Javascript的number.toLocaleString需要指定货币符号,而我无法找到如何告诉它根本不显示。

我尝试过的:

number.toLocaleString('de-DE', { style: 'currency' }));
// TypeError: undefined currency in NumberFormat() with currency style

number.toLocaleString('de-DE', { style: 'currency', currency: '' }));
// RangeError: invalid currency code in NumberFormat():

number.toLocaleString('de-DE', { style: 'currency', currency: false }));
// RangeError: invalid currency code in NumberFormat(): false

number.toLocaleString('de-DE', { style: 'currency', currency: null }));
// RangeError: invalid currency code in NumberFormat(): null

该函数还具有选项currencyDisplay。我尝试了与上述相同的值,但使用currency选项得到了相同的结果。


更新(2020年11月25日)

一些人指出了.resolvedOptions()。它基本上解决了这个问题:

const currencyFractionDigits = new Intl.NumberFormat('de-DE', {
    style: 'currency',
    currency: 'EUR',
}).resolvedOptions().maximumFractionDigits;

const value = (12345.678).toLocaleString('de-DE', {
    maximumFractionDigits: currencyFractionDigits 
});

console.log(value); // prints 12.345,68

谢谢。


以下声明是错误的:“问题在于 JavaScript 的 number.toLocaleString 需要指定货币符号”。你可以简单地传递区域设置字符串,例如 number.toLocaleString('de-DE') - Giorgio Tempesta
1
如果您希望将$ 0.50格式化为0.50而不是0.5,则对我来说{minimumFractionDigits:currencyFractionDigits}是有效的。 - user3002996
14个回答

22

无法通过toLocaleString传递参数并删除货币符号,因此请改用此函数。

var convertedNumber = num.toLocaleString('de-DE', { minimumFractionDigits: 2 });


我怎么知道当前货币小数位的数量?它可能为0、2或3。 - dMedia
复制我的代码行到一个函数中,并将小数位作为参数传递给一个变量。我正在使用相同的方法,这就是minimumFractionDigits的用处。 - Shahzaib Hayat Khan
2
我知道在哪里传递小数位,但我不知道如何在JavaScript中获取该数字。 - dMedia
1
我并不是想冒犯你或者质疑你的编程技能。兄弟,也许我没有正确理解你的问题。 - Shahzaib Hayat Khan
4
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).resolvedOptions() 返回一个对象,其中包括了如何格式化数字的描述,包括 minimumIntegerDigitsminimumFractionDigitsmaximumFractionDigits 字段。 - Aner
如何获取其他格式选项 - 分数和千位分隔符?完整的代码将会非常有用。 - Alexander Pravdin

18

这是我解决这个问题的方法。当我想要格式化没有任何符号的货币时,我会使用货币代码进行格式化,然后只需从结果中删除3个字符的代码即可。

export function getCurrencyFormatWithSymbol(currencyCode) {
  return {
    style: 'currency',
    currency: currencyCode,
    currencyDisplay: 'symbol',
  }
}

export function getCurrencyFormatWithIsoCode(currencyCode) {
  return {
    style: 'currency',
    currency: currencyCode,
    currencyDisplay: 'code',
  }
}

export function getCurrencyFormatWithLocalName(currencyCode) {
  return {
    style: 'currency',
    currency: currencyCode,
    currencyDisplay: 'name',
  }
}

export function getCurrencyFormatNumbersOnly(currencyCode) {
  return {
    style: 'currency',
    currency: currencyCode,
    currencyDisplay: 'none',
  }
}

export function formatCurrency (value, format, lang) {
  const stripSymbols = (format.currencyDisplay === 'none')
  const localFormat = stripSymbols ? {...format, currencyDisplay: 'code'} : format
  let result = Intl.NumberFormat(lang, localFormat).format(value)
  if (stripSymbols) {
    result = result.replace(/[a-z]{3}/i, "").trim()
  }
  return result
}

使用方法:

const format = getCurrencyFormatNumbersOnly('JPY')
formatCurrency(12345, format, 'ja')
formatCurrency(123456, format, 'ja')
formatCurrency(1234567, format, 'ja')
formatCurrency(12345678, format, 'ja')

编辑:唯一的缺点是速度。在简单任务上,它可以完美地工作。但是,如果您要格式化大量数字(例如,如果您正在从后端获取原始数据并根据用户设置格式化数字的财务报告),此函数可能会显着减慢算法速度,并成为某些浏览器上的瓶颈。因此,在生产中使用之前,请仔细测试。


1
这很有用,但我仍然希望在 number.toLocaleString 中有一个我们不知道的选项。 - dMedia
似乎您的问题无法通过本地JS工具解决。我曾经搜索过相同的问题,但没有找到任何解决方案。因此,在我的项目中唯一可行的方法就是我上面展示的方式。 - Alexander Pravdin
1
currencyDisplay: "none" 不是有效的。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat - Ray
1
@Ray 如果你仔细看代码,你会发现 none 值只在我的代码中使用,而不是传递给 Intl.NumberFormat() 方法。相反,如果配置中使用了 none,它将被 code 值替换。none 值仅用于配置我的自定义函数。 - Alexander Pravdin

9
这里有一个解决方案,不使用正则表达式,并且可以正确处理任何语言环境。
它使用区域设置的货币格式化程序,并迭代其所有部分以排除文字和货币等,从而只获取数字作为字符串。 (顺便说一句,文字是数字和货币符号之间的空格)。

const value = new Intl.NumberFormat('de-DE', {
    style: 'currency',
    currency: 'EUR',
}).formatToParts(12345.678).map(
    p => p.type != 'literal' && p.type != 'currency' ? p.value : ''
).join('')

console.log(value) // prints 12.345,68


这个看起来很聪明,但不幸的是并不起作用。它没有考虑到所有货币-语言环境组合特定的选项。在fr-CHCHF的情况下,它将使用小数逗号而不是小数点。 https://jsfiddle.net/e80vutwq/ - KohlerDominik
@KohlerDominik 您说得对,我更新了我的答案来修复这个问题。问题在于toLocaleStringstyle: 'decimal'将使用给定语言的数字小数符号,而不是货币小数符号。在调用toLocaleString时无法设置小数符号,但是我找到了一个更简单的解决方案。只需使用货币格式化程序并使用formatToParts提取所有部分(不包括货币符号)。请查看我的更新答案。 - Martin Braun
是的,现在它会工作了。它现在实际上是@nyg下面那个的副本。 - KohlerDominik
@KohlerDominik 哦,我没有看到他的答案,是自己解决的。我可以看出他的解决方案不会排除文字并修剪值,但这仅适用于使用空格作为文字的货币。此外,我正在连接段落,而他使用reduce。我并不打算接近已经存在的解决方案,但我的解决方案应该稍微快一些,更加可靠。 - Martin Braun

3
在OP答案的基础上稍作改动,包括最小分数位数(minimumFractionDigits)。
const resolvedOptions = new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP', }).resolvedOptions();
const currencyOptions = {
    minimumFractionDigits: resolvedOptions.minimumFractionDigits,
    maximumFractionDigits: resolvedOptions.maximumFractionDigits
}
const value = (12345.678).toLocaleString('en-GB', currencyOptions)

3

原帖中提出的解决方案无法适用于fr-CH语言环境,因为在该环境下,“货币金额”和“非货币金额”有所区别。前者使用点作为小数分隔符,而后者使用逗号:

const n = 1234.56
console.log(n.toLocaleString('fr-CH'))
console.log(n.toLocaleString('fr-CH', {
  style: 'currency',
  currency: 'CHF'
}))

使用 .replace() 函数,可以直接使用货币代码或正则表达式进行替换,这似乎是最快的解决方法。但是,这里提供了一种使用 .formatToParts() 函数来解决 OP 问题的解决方案:

console.log(new Intl
  .NumberFormat('fr-CH', { style: 'currency', currency: 'CHF' })
  .formatToParts(1234.56) // returns an array of the different parts of the amount
  .filter(p => p.type != 'currency') // removes the currency part
  .reduce((s, p) => s + p.value, '') // joins the remaining values
  .trim())


2

您可以使用 currencyDisplay: 'code' 选项,由于您知道货币代码,因此您可以轻松地用您想要的符号替换它:

return Intl.NumberFormat(language, {
    style: 'currency', currency: currency.code, currencyDisplay: 'code'
  }).format(amount).replace(currency.code, currency.symbol);

这样做可以保持NumberFormat中涉及的所有货币格式标准,并仅替换符号。在您的情况下,自定义符号将是一个空字符串(''),您可能还想使用.trim()修剪字符串。


1

你只需要用符号将字符串分割,然后获取数组的第二个值。

// value 350011
 const valueFormated = (value).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD',
 });

 valueFormated.split('$')
 // if you console.log the result would be
 (2) ['', '3,500.11']

 // here is the value formated
 valueFormated.split('$')[1]
 // 3,500.11

拆分并不是一个好的选项,因为有些货币符号会出现在数字之后,你无法猜测。 - Adam A Allalou
从我的测试来看,currencyDisplay的位置是由语言环境设置的。如果你使用'en',它将始终位于开头,而'de'则在结尾。因此,如果您设置语言环境,应该会有一个可靠的位置。@AdamAAllalou - Sebastian Thomas

1
我通过搜索这个使用情景找到了这个帖子,我使用了 Intl.NumberFormat 类和支持在 Mozilla Firefox 和 Google Chrome 上的符号正则表达式技巧。这个技巧是将货币符号作为正则表达式替换的针,以进行本地化处理。
以下示例代码应该可以解决问题:
var number = 123456.789;

function getCurrencySymbol(locale, currency) {
  return (0).toLocaleString(locale, {
    style: 'currency',
    currency: currency,
    minimumFractionDigits: 0,
    maximumFractionDigits: 0
  }).replace(/\d/g, '').trim();
}
var numeric_format = new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', currencyDisplay: 'symbol' });
var localCurrencySymbol  = getCurrencySymbol('id-ID', 'IDR');
var CurrencySymbolNeedle = new RegExp(localCurrencySymbol, "g");

var amount = numeric_format.format(number);
console.log(localCurrencySymbol); // Rp
console.log(amount); // Rp 123.456,79
amount = amount.replace(CurrencySymbolNeedle, '').replace(/\s+/g, '');
console.log(amount); // 123.456,79

我不测试这个类是否支持跨浏览器。
编辑: 获取货币符号的函数取自获取区域设置的货币符号

0
你需要货币符号吗?如果不需要,number.toLocaleString('de-DE') 就可以解决问题了。

4
我该如何知道本地货币小数位的数量?它可能是0、2或3:https://www.currency-iso.org/en/home/tables/table-a1.html - dMedia
抱歉,我觉得我可能误解了您的意思。您的使用情况是什么? - Cornelius Fillmore
2
@dMedia。new Intl.NumberFormat('en', { style: 'currency', currency: 'EUR', }).resolvedOptions().maximumFractionDigits - Karolis.sh

0
const locale = 'en-US';
const currency = 'USD';

const getCurrencySymbol = () =>
  (0)
    .toLocaleString(locale, {
      style: 'currency',
      currency: currency,
      maximumFractionDigits: 0,
      minimumFractionDigits: 0,
    })
    .replace(/\d/g, '')
    .trim();

const formattedNumberWithoutSymbol = new Intl.NumberFormat(locale, {
  style: 'currency',
  currency: currency,
}).format(499.99).replace(getCurrencySymbol(), '');

console.log(formattedNumberWithoutSymbol);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接