Does Intl-Dart numberformat parse wrong of a dot number in pt_BR?

Asked

Viewed 24 times

0

I’m using the package lntl Dart to parse decimal numbers. When setting the locale to 'pt_BR', I would expect a number in English format (1.5 instead of 1.5) to release a Formatexception. But he does the parse by ignoring the point:

print(NumberFormat.decimalPattern('pt_BR').parse('1.5'))
15.0

I’m missing something stupid, or is that right? This would be a bug in the package Intl (seems unlikely to me)?

1 answer

3


Well, it may sound strange but that’s how lib was developed. For locale pt_BR the character . (point) is considered a group separation character (GROUP_SEP).

Source: filing cabinet number_symbols_data.dart:

"pt_BR": new NumberSymbols(
      NAME: "pt_BR",
      DECIMAL_SEP: ',',
      GROUP_SEP: '.',
      PERCENT: '%',
      ZERO_DIGIT: '0',
      PLUS_SIGN: '+',
      MINUS_SIGN: '-',
      EXP_SYMBOL: 'E',
      PERMILL: '\u2030',
      INFINITY: '\u221E',
      NAN: 'NaN',
      DECIMAL_PATTERN: '#,##0.###',
      SCIENTIFIC_PATTERN: '#E0',
      PERCENT_PATTERN: '#,##0%',
      CURRENCY_PATTERN: '\u00A4\u00A0#,##0.00',
      DEF_CURRENCY_CODE: 'BRL')

And because it is recognized as a separation character, it is simply ignored during the parse of the number. After all in pt_BR a number 1.234.567,00 is the same thing as 1234567,00. Therefore a 1.5 turns out to be a 15.

Source: part of the function processNonDigit() of the archive number_parser.dart:

  void processNonDigit() {
    // It might just be a prefix that we haven't skipped. We don't want to
    // skip them initially because they might also be semantically meaningful,
    // e.g. leading %. So we allow them through the loop, but only once.
    var foundAnInterpretation = false;
    if (input.index == 0 && !prefixesSkipped) {
      prefixesSkipped = true;
      checkPrefixes(skip: true);
      foundAnInterpretation = true;
    }

    for (var key in replacements.keys) {
      if (input.startsWith(key)) {
        _normalized.write(replacements[key]!()); // aqui
        input.read(key.length);
        return;
      }
    }
    // We haven't found either of these things, this seems invalid.
    if (!foundAnInterpretation) {
      done = true;
    }
  }

In this function the chunk is where the call of map values occurs replacements[key]!(). That if you dig deeper you’ll see that for this GROUP_SEP is called another function handleSpace() to handle values that are indifferent to the number format in the locale.

  • 1

    Interesting, thanks for the detailed answer. I would imagine that lib would check that it has 3 digits after GROUP_SEP (maybe this rule is more complex for other languages?). I will add a proper validation for 'dot not followed by 3 digits' before sending it to lib then.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.