'Is there a way to reverse the formatting by Intl.NumberFormat in JavaScript

The Intl.NumberFormat (see Mozilla's doc) provides a nice way in Javascript to format numbers into a current locale`s version like this:

new Intl.NumberFormat().format(3400); // returns "3.400" for German locale

But I couldn't find a way to reverse this formatting. Is there something like

new Intl.NumberFormat().unformat("3.400"); // returns 3400 for German locale

Thanks for any help.



Solution 1:[1]

Here I have created a function for Reverse of format() function. This function will support reverse formatting in all locales.

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'));

Solution 2:[2]

I just solved it using group replacers

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 = '$10.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>

Solution 3:[3]

what I've done so far is a multi step approach which you can see in the below code. nf is the NumberFormat service. This function takes the formatted number as well as the used locale. Now we create a comparator by dividing 10k by 3 thus guaranteeing a decimal and thousandSeparator at a fixed position. Then remove the thousand separator and all other non-numeric signs, like currency symbols. after that we replace the decimal separator with the english one and finally return a casted number.

  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);
  }

Solution 4:[4]

Not sure of the relevance of this approach performance-wise, but it's always good to have several options, so here is another one :

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('.');
}

In my case the locale is set from PHP, so I get it with <?php echo cms_function_to_get_decimal_point(); ?>, but obviously one can use the division trick suggested in other answers instead.

Solution 5:[5]

I have tried the accepted answer and agree with that. So I upvoted as well. I may have another workaround without specifying any local, but instead look for the separator manually.

P.s. The digit argument is used to specify the amount of decimal places.

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;
}

Example to use this method:

console.log(parseLocaleNumber('123,456,789.12'));
// 123456789.12

The code is written with the use of TypeScript.

Solution 6:[6]

A dummy solution maybe

const getInformattedMoney = (formattedValue) => Number(formmattedValue.replaceAll('.','').replaceAll(',','.').replace(`${currencySymbol}`,''))

For me the . (dot) is thousand seperator and the , (comma) is double seperator

Solution 7:[7]

You can use the formatToParts method available on the instance, this is generally better as you can ignore the currency and group separators this way

  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

Solution 8:[8]

You should be able to just use:

value.replace(/\D/g, '');

As any added formatting is going to be non digits

Solution 9:[9]

Is not very clean, but works for me:

//value is "in-En" format --> $1,200.51
function unformatter(value){
    value = value.replace("$","");
    value = value.replace(",","");
    value = parseFloat(value);
    return(value); //returns --> 1200.51
};

Solution 10:[10]

What about using Math? Take a look:

const usd = '$204.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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Saqib Ahmed
Solution 2
Solution 3 zewa666
Solution 4 Skippy le Grand Gourou
Solution 5 JW Geertsma
Solution 6 Keyyubi
Solution 7 Shannon Hochkins
Solution 8 Ben
Solution 9
Solution 10 Pankwood