Does JavaScript take local decimal separators into account?

前端 未结 7 799
陌清茗
陌清茗 2020-12-10 06:26

I\'ve got a web page that displays decimals in a user\'s localized format, like so:

  • English: 7.75
  • Dutch: 7,75

相关标签:
7条回答
  • 2020-12-10 07:03

    Expanding on the solution from @naitsirch we can use Intl.NumberFormat.formatToParts() to have JS parse the group and 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

    0 讨论(0)
  • 2020-12-10 07:04

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

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

    0 讨论(0)
  • 2020-12-10 07:06

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

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

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

    0 讨论(0)
  • 2020-12-10 07:09

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

    0 讨论(0)
  • 2020-12-10 07:09

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

    function parseLocaleNumber(stringNumber) {
        var thousandSeparator = (1111).toLocaleString().replace(/1/g, '');
        var decimalSeparator = (1.1).toLocaleString().replace(/1/g, '');
    
        return parseFloat(stringNumber
            .replace(new RegExp('\\' + thousandSeparator, 'g'), '')
            .replace(new RegExp('\\' + decimalSeparator), '.')
        );
    }
    

    It uses the current locale of the browser to replace thousand and decimal separators.

    With a German locale setting

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

    n will be equal to 1000045.22.

    0 讨论(0)
  • 2020-12-10 07:15

    Taking the symbol into account, this works 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
    0 讨论(0)
提交回复
热议问题