有没有办法通过 JavaScript 中的 Intl.NumberFormat 反转格式
Is there a way to reverse the formatting by Intl.NumberFormat in JavaScript
Intl.NumberFormat
(参见 Mozilla's doc)在 Javascript 中提供了一种将数字格式化为当前语言环境版本的好方法,如下所示:
new Intl.NumberFormat().format(3400); // returns "3.400" for German locale
但是我找不到反转这种格式的方法。
有没有类似
new Intl.NumberFormat().unformat("3.400"); // returns 3400 for German locale
感谢您的帮助。
我找到了解决方法:
/**
* Parse a localized number to a float.
* @param {string} stringNumber - the localized number
* @param {string} locale - [optional] the locale that the number is represented in. Omit this parameter to use the current locale.
*/
function parseLocaleNumber(stringNumber, locale) {
var thousandSeparator = Intl.NumberFormat(locale).format(11111).replace(/\p{Number}/gu, '');
var decimalSeparator = Intl.NumberFormat(locale).format(1.1).replace(/\p{Number}/gu, '');
return parseFloat(stringNumber
.replace(new RegExp('\' + thousandSeparator, 'g'), '')
.replace(new RegExp('\' + decimalSeparator), '.')
);
}
这样使用:
parseLocaleNumber('3.400,5', 'de');
parseLocaleNumber('3.400,5'); // or if you have German locale settings
// results in: 3400.5
不是最好的解决方案,但它有效:-)
如果有人知道实现此目的的更好方法,请随时post回答。
更新
- 包装在一个完整的可重用函数中
- 使用正则表达式 class
\p{Number}
提取分隔符。所以它也适用于非阿拉伯数字。
- 使用 5 位数字来支持每四位数字分隔一次的语言。
到目前为止我所做的是一种多步骤方法,您可以在下面的代码中看到。 nf 是 NumberFormat 服务。此函数采用格式化数字以及使用的语言环境。现在我们通过将 10k 除以 3 创建一个比较器,从而保证在固定位置有一个 decimal 和 thousandSeparator。然后删除千位分隔符和所有其他非数字符号,如货币符号。之后我们用英文替换小数点分隔符,最后 return 一个铸造数字。
uf(number, locale) {
let nf = this.nf({}, locale);
let comparer = nf.format(10000 / 3);
let thousandSeparator = comparer[1];
let decimalSeparator = comparer[5];
// remove thousand seperator
let result = number.replace(thousandSeparator, '')
// remove non-numeric signs except -> , .
.replace(/[^\d.,-]/g, '')
// replace original decimalSeparator with english one
.replace(decimalSeparator, '.');
// return real number
return Number(result);
}
在这里,我创建了一个用于 format()
函数反转的函数。
此功能将支持所有语言环境中的反向格式化。
function reverseFormatNumber(val,locale){
var group = new Intl.NumberFormat(locale).format(1111).replace(/1/g, '');
var decimal = new Intl.NumberFormat(locale).format(1.1).replace(/1/g, '');
var reversedVal = val.replace(new RegExp('\' + group, 'g'), '');
reversedVal = reversedVal.replace(new RegExp('\' + decimal, 'g'), '.');
return Number.isNaN(reversedVal)?0:reversedVal;
}
console.log(reverseFormatNumber('1,234.56','en'));
console.log(reverseFormatNumber('1.234,56','de'));
不确定这种方法在性能方面的相关性,但有多种选择总是好的,所以这里是另一个:
function getNumPrice(price, decimalpoint) {
var p = price.split(decimalpoint);
for (var i=0;i<p.length;i++) p[i] = p[i].replace(/\D/g,'');
return p.join('.');
}
在我的例子中,语言环境是从 PHP 设置的,所以我用 <?php echo cms_function_to_get_decimal_point(); ?>
得到它,但显然可以使用其他答案中建议的除法技巧。
您应该可以使用:
value.replace(/\D/g, '');
因为任何添加的格式都将是非数字
不是很干净,但适合我:
//value is "in-En" format --> ,200.51
function unformatter(value){
value = value.replace("$","");
value = value.replace(",","");
value = parseFloat(value);
return(value); //returns --> 1200.51
};
我刚刚使用组替换器解决了它
const exp = /^\w{0,3}\W?\s?(\d+)[.,](\d+)?,?(\d+)?$/g
const replacer = (f, group1, group2, group3) => {
return group3 ?
`${group1}${group2}.${group3}` :
`${group1}.${group2}`
}
const usd = '.15'.replace(exp, replacer)
// 10.15
const eu = '€01.25'.replace(exp, replacer)
// 1.25
const brl = 'R$ 14.000,32'.replace(exp, replacer)
// 14000.32
const tai = 'TAI 50.230,32'.replace(exp, replacer)
// 50230.32
// just to test!
const el = document.getElementById('output')
const reverseUSD = new Intl.NumberFormat('en-us', { style: 'currency', currency: 'USD' }).format(usd)
el.innerHTML += `<br> from: ${reverseUSD} to ${parseFloat(usd)}`
const reverseBRL = new Intl.NumberFormat('pt-br', { style: 'currency', currency: 'BRL' }).format(brl)
el.innerHTML += `<br> from: ${reverseBRL} to ${parseFloat(brl)}`
const reverseTAI = new Intl.NumberFormat('en-us', { style: 'currency', currency: 'TAI' }).format(tai)
el.innerHTML += `<br> from: ${reverseTAI} to ${parseFloat(tai)}`
const reverseEU = new Intl.NumberFormat('eur', { style: 'currency', currency: 'EUR' }).format(eu)
el.innerHTML += `<br> from: ${reverseEU} to ${parseFloat(eu)}`
<output id=output></output>
使用数学怎么样?看看:
const usd = '4.201,32'
const brl = 'R$ 14.000,32'
const stringToDecimal = (string = '') => Number(string.replace(/\D/g, '')) / 100
const usdToDecimal = stringToDecimal(usd) // outputs: USD To Decimal: 204201.32
const brlToDecimal = stringToDecimal(brl) // outputs: BRL To Decimal: 14000.32
我已经尝试过接受的答案并同意。所以我也投了赞成票。我可能有另一种解决方法而不指定任何本地,而是手动查找分隔符。
P.s。数字参数用于指定小数位数。
parseLocaleNumber(stringnum: string, digit: number): number {
let retValue: number = parseFloat(stringnum);
var arr: string[] = stringnum.split('');
arr.slice().reverse().forEach((x, i, arr) => {
if (i === digit) {
if (x === '.') {
retValue = parseFloat(stringnum.split(',').join(''));
arr.length = i + 1;
} else if (x === ',') {
retValue = parseFloat(stringnum.split('.').join(''));
arr.length = i + 1;
}
}
});
return retValue;
}
使用此方法的示例:
console.log(parseLocaleNumber('123,456,789.12'));
// 123456789.12
代码是使用 TypeScript 编写的。
可能是虚拟解决方案
const getInformattedMoney = (formattedValue) => Number(formmattedValue.replaceAll('.','').replaceAll(',','.').replace(`${currencySymbol}`,''))
对我来说,.
(点)是千位分隔符,,
(逗号)是双分隔符
您可以使用实例上可用的 formatToParts 方法,这通常更好,因为您可以通过这种方式忽略货币和组分隔符
function convertToFloat(number, locale = 'en', currency = 'AUD') {
const instance = new Intl.NumberFormat(locale, {
style: 'currency',
currency,
});
const roundedValue = instance.formatToParts(number)
.filter(part => !['currency', 'group'].includes(part.type))
.reduce((acc, part) => `${acc}${part.value}`, '').replace(/,/g, '.');
// then just parse it as a float
return [instance.format(number), '->', parseFloat(roundedValue)];
}
console.log(convertToFloat(1234.56)); // -> 1234.56
console.log(convertToFloat(1234.56, 'de-DE', 'EUR')); // -> 1234.56
Intl.NumberFormat
(参见 Mozilla's doc)在 Javascript 中提供了一种将数字格式化为当前语言环境版本的好方法,如下所示:
new Intl.NumberFormat().format(3400); // returns "3.400" for German locale
但是我找不到反转这种格式的方法。 有没有类似
new Intl.NumberFormat().unformat("3.400"); // returns 3400 for German locale
感谢您的帮助。
我找到了解决方法:
/**
* Parse a localized number to a float.
* @param {string} stringNumber - the localized number
* @param {string} locale - [optional] the locale that the number is represented in. Omit this parameter to use the current locale.
*/
function parseLocaleNumber(stringNumber, locale) {
var thousandSeparator = Intl.NumberFormat(locale).format(11111).replace(/\p{Number}/gu, '');
var decimalSeparator = Intl.NumberFormat(locale).format(1.1).replace(/\p{Number}/gu, '');
return parseFloat(stringNumber
.replace(new RegExp('\' + thousandSeparator, 'g'), '')
.replace(new RegExp('\' + decimalSeparator), '.')
);
}
这样使用:
parseLocaleNumber('3.400,5', 'de');
parseLocaleNumber('3.400,5'); // or if you have German locale settings
// results in: 3400.5
不是最好的解决方案,但它有效:-)
如果有人知道实现此目的的更好方法,请随时post回答。
更新
- 包装在一个完整的可重用函数中
- 使用正则表达式 class
\p{Number}
提取分隔符。所以它也适用于非阿拉伯数字。 - 使用 5 位数字来支持每四位数字分隔一次的语言。
到目前为止我所做的是一种多步骤方法,您可以在下面的代码中看到。 nf 是 NumberFormat 服务。此函数采用格式化数字以及使用的语言环境。现在我们通过将 10k 除以 3 创建一个比较器,从而保证在固定位置有一个 decimal 和 thousandSeparator。然后删除千位分隔符和所有其他非数字符号,如货币符号。之后我们用英文替换小数点分隔符,最后 return 一个铸造数字。
uf(number, locale) {
let nf = this.nf({}, locale);
let comparer = nf.format(10000 / 3);
let thousandSeparator = comparer[1];
let decimalSeparator = comparer[5];
// remove thousand seperator
let result = number.replace(thousandSeparator, '')
// remove non-numeric signs except -> , .
.replace(/[^\d.,-]/g, '')
// replace original decimalSeparator with english one
.replace(decimalSeparator, '.');
// return real number
return Number(result);
}
在这里,我创建了一个用于 format()
函数反转的函数。
此功能将支持所有语言环境中的反向格式化。
function reverseFormatNumber(val,locale){
var group = new Intl.NumberFormat(locale).format(1111).replace(/1/g, '');
var decimal = new Intl.NumberFormat(locale).format(1.1).replace(/1/g, '');
var reversedVal = val.replace(new RegExp('\' + group, 'g'), '');
reversedVal = reversedVal.replace(new RegExp('\' + decimal, 'g'), '.');
return Number.isNaN(reversedVal)?0:reversedVal;
}
console.log(reverseFormatNumber('1,234.56','en'));
console.log(reverseFormatNumber('1.234,56','de'));
不确定这种方法在性能方面的相关性,但有多种选择总是好的,所以这里是另一个:
function getNumPrice(price, decimalpoint) {
var p = price.split(decimalpoint);
for (var i=0;i<p.length;i++) p[i] = p[i].replace(/\D/g,'');
return p.join('.');
}
在我的例子中,语言环境是从 PHP 设置的,所以我用 <?php echo cms_function_to_get_decimal_point(); ?>
得到它,但显然可以使用其他答案中建议的除法技巧。
您应该可以使用:
value.replace(/\D/g, '');
因为任何添加的格式都将是非数字
不是很干净,但适合我:
//value is "in-En" format --> ,200.51
function unformatter(value){
value = value.replace("$","");
value = value.replace(",","");
value = parseFloat(value);
return(value); //returns --> 1200.51
};
我刚刚使用组替换器解决了它
const exp = /^\w{0,3}\W?\s?(\d+)[.,](\d+)?,?(\d+)?$/g
const replacer = (f, group1, group2, group3) => {
return group3 ?
`${group1}${group2}.${group3}` :
`${group1}.${group2}`
}
const usd = '.15'.replace(exp, replacer)
// 10.15
const eu = '€01.25'.replace(exp, replacer)
// 1.25
const brl = 'R$ 14.000,32'.replace(exp, replacer)
// 14000.32
const tai = 'TAI 50.230,32'.replace(exp, replacer)
// 50230.32
// just to test!
const el = document.getElementById('output')
const reverseUSD = new Intl.NumberFormat('en-us', { style: 'currency', currency: 'USD' }).format(usd)
el.innerHTML += `<br> from: ${reverseUSD} to ${parseFloat(usd)}`
const reverseBRL = new Intl.NumberFormat('pt-br', { style: 'currency', currency: 'BRL' }).format(brl)
el.innerHTML += `<br> from: ${reverseBRL} to ${parseFloat(brl)}`
const reverseTAI = new Intl.NumberFormat('en-us', { style: 'currency', currency: 'TAI' }).format(tai)
el.innerHTML += `<br> from: ${reverseTAI} to ${parseFloat(tai)}`
const reverseEU = new Intl.NumberFormat('eur', { style: 'currency', currency: 'EUR' }).format(eu)
el.innerHTML += `<br> from: ${reverseEU} to ${parseFloat(eu)}`
<output id=output></output>
使用数学怎么样?看看:
const usd = '4.201,32'
const brl = 'R$ 14.000,32'
const stringToDecimal = (string = '') => Number(string.replace(/\D/g, '')) / 100
const usdToDecimal = stringToDecimal(usd) // outputs: USD To Decimal: 204201.32
const brlToDecimal = stringToDecimal(brl) // outputs: BRL To Decimal: 14000.32
我已经尝试过接受的答案并同意。所以我也投了赞成票。我可能有另一种解决方法而不指定任何本地,而是手动查找分隔符。
P.s。数字参数用于指定小数位数。
parseLocaleNumber(stringnum: string, digit: number): number {
let retValue: number = parseFloat(stringnum);
var arr: string[] = stringnum.split('');
arr.slice().reverse().forEach((x, i, arr) => {
if (i === digit) {
if (x === '.') {
retValue = parseFloat(stringnum.split(',').join(''));
arr.length = i + 1;
} else if (x === ',') {
retValue = parseFloat(stringnum.split('.').join(''));
arr.length = i + 1;
}
}
});
return retValue;
}
使用此方法的示例:
console.log(parseLocaleNumber('123,456,789.12'));
// 123456789.12
代码是使用 TypeScript 编写的。
可能是虚拟解决方案
const getInformattedMoney = (formattedValue) => Number(formmattedValue.replaceAll('.','').replaceAll(',','.').replace(`${currencySymbol}`,''))
对我来说,.
(点)是千位分隔符,,
(逗号)是双分隔符
您可以使用实例上可用的 formatToParts 方法,这通常更好,因为您可以通过这种方式忽略货币和组分隔符
function convertToFloat(number, locale = 'en', currency = 'AUD') {
const instance = new Intl.NumberFormat(locale, {
style: 'currency',
currency,
});
const roundedValue = instance.formatToParts(number)
.filter(part => !['currency', 'group'].includes(part.type))
.reduce((acc, part) => `${acc}${part.value}`, '').replace(/,/g, '.');
// then just parse it as a float
return [instance.format(number), '->', parseFloat(roundedValue)];
}
console.log(convertToFloat(1234.56)); // -> 1234.56
console.log(convertToFloat(1234.56, 'de-DE', 'EUR')); // -> 1234.56