[ACCEPTED]-Does JavaScript take local decimal separators into account?-localization

Accepted answer
Score: 22

Here's an example for a locale aware number 5 parser:

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

It uses the passed locale (or the 4 current locale of the browser if locale 3 parameter is undefined) to replace thousand 2 and decimal separators.

With a German locale 1 setting

var n = parseLocaleNumber('1.000.045,22');

n will be equal to 1000045.22.

Update:

  • Addressed Pointy's comment by using the regex class \p{Number} for removing digits. So that it also works with non-arabic digits.
  • Addressed Orion Adrian's comment to support languages where numbers are separated at every fourth digits.
  • Added locale parameter to sepcify different locales for parsing.
Score: 12

No, the separator is always a dot (.) in 9 a javascript Number. So 7,75 evaluates to 75, because 8 a , invokes left to right evaluation (try 7 it in a console: x=1,x+=1,alert(x), or more to the point 6 var x=(7,75); alert(x);). If you want to convert a Dutch (well, not 5 only Dutch, let's say Continental European) formatted 4 value, it should be a String. You could write 3 an extension to the String prototype, something 2 like:

String.prototype.toFloat = function(){
      return parseFloat(this.replace(/,(\d+)$/,'.$1'));
};
//usage
'7,75'.toFloat()+'7,75'.toFloat(); //=> 15.5

Note, if the browser supports it you 1 can use Number.toLocaleString

console.log((3.32).toLocaleString("nl-NL"));
console.log((3.32).toLocaleString("en-UK"));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Score: 5

Expanding on the solution from @naitsirch 2 we can use Intl.NumberFormat.formatToParts() to have JS parse the group and 1 decimal separators.

function parseLocaleNumber(stringNumber) {
  let num = 123456.789,
    fmt_local = new Intl.NumberFormat(),
    parts_local = fmt_local.formatToParts(num),
    group = '',
    decimal = '';

  parts_local.forEach(function(i) {
    switch (i.type) {
      case 'group':
        group = i.value;
        break;
      case 'decimal':
        decimal = i.value;
        break;
      default:
        break;
    }
  });

  return parseFloat(stringNumber
    .replace(new RegExp('\\' + group, 'g'), '')
    .replace(new RegExp('\\' + decimal), '.')
  );
}

//replace this string with a number formatted for your locale
console.log(parseLocaleNumber("987,654,321.01"));
//output for "en" locale: 987654321.01
Score: 3

Expanding on the solution from @OXiGEN we 2 can use Intl.NumberFormat.formatToParts() to extract also the currency symbol 1 :)

function parseLocaleNumber(stringNumber, locale, currency_code) {
  let num = 123456.789,
    fmt_local = new Intl.NumberFormat(locale, {
      style: 'currency',
      currency: currency_code
    }),
    parts_local = fmt_local.formatToParts(num),
    group = '',
    decimal = '',
    currency = '';

  // separators
  parts_local.forEach(function(i) {
    //console.log(i.type + ':' + i.value);
    switch (i.type) {
      case 'group':
        group = i.value;
        break;
      case 'decimal':
        decimal = i.value;
        break;
      case 'currency':
        currency = i.value;
        break;
      default:
        break;
    }
  });

  return parseFloat(stringNumber
    .replace(new RegExp('\\' + group, 'g'), '')
    .replace(new RegExp('\\' + decimal), '.')
    .replace(new RegExp('\\' + currency, 'g'), '')
  );
}

//replace inputs with a number formatted for your locale, your locale code, your currency code
console.log(parseLocaleNumber('$987,654,321.01', 'en', 'USD'));
//output for "en" locale and "USD" code: 987654321.01
Score: 2

No, comma (,) is an operator having special 5 meaning, just like dot (.). Otherwise things 4 as simple as:

var array1 = [1,2];
var array2 = [1.2];

would break under different 3 locales. All mainstream languages I know 2 treat . and , separately and stricly, irrespective 1 to locale.

Score: 1

No, decimal separators are not localized 14 at all in JavaScript, and parseFloat() parses 13 numbers in the same format as you need to 12 use in JavaScript source code: “.” as decimal 11 separator, no group (thousands) separator, “E” or 10 “e” as “times ten to power” symbol, and 9 Ascii hyphen “-” as minus sign.

To read or 8 write numbers in localized format, you need 7 something else. I would recommend the Globalize.js 6 library, unless you can limit yourself to 5 the single issue of decimal separator and 4 a limited number of languages—in that case, it 3 might be simpler to do just string manipulation 2 that maps “.” to “,” on output and vice 1 versa on input.

Score: 0

Taking the symbol into account, this works 1 in all cases:

parseLocaleNumber: function ( stringNumber ) 
{
    let thousandSeparator = (11111).toLocaleString().replace(/1/g, '');
    let decimalSeparator = (1.1).toLocaleString().replace(/1/g, '');
    let symbol = (0).toLocaleString()
        .replace(/0/g, '')
        .replace(new RegExp('\\' + decimalSeparator), '.')
        .trim();

    return parseFloat(
        stringNumber
            .replace(new RegExp('\\' + thousandSeparator, 'g'), '')
            .replace(new RegExp('\\' + decimalSeparator), '.')
            .replace(new RegExp( symbol ), '')
    );
}

2 details highlighted:

  1. use 11111 instead of 1111 because the first always shows thousand separator by default.
  2. Number format always uses '.' as decimal separator

More Related questions