Выясните, неправильно ли я понимаю форматирование чисел или неправильно его использую для анализа и проверки - PullRequest
0 голосов
/ 21 июня 2019

Попытка использовать Числовой форматер для анализа и проверки ввода пользователя для целых чисел (тип форматера = DECIMAL). Возможно, это академично, но я хочу иметь возможность изменить разделитель группировки, отличающийся от соглашений, установленных в локали. Например, в США разделитель группировки («разделитель тысяч») по умолчанию является запятой (','). Изменение разделителя на группы приводит к неожиданным результатам (см. Код модульного теста ниже). Я не уверен, что форматировщик просто не будет делать то, что я хочу, или я делаю это неправильно (например, должен ли тип форматера = PATTERN_DECIMAL). Если тип форматера должен быть PATTERN_DECIMAL, есть ли где-нибудь полезная документация? Документация ICU ... ммм ... не так полезна, как могла бы быть.

$this->frmtr = new \NumberFormatter('en-US', NumberFormatter::DECIMAL)         

function testGroupingSeparator() {

    $expectedResult = 12345;
    $this->assertEquals($expectedResult, $this->frmtr->parse("12,345", NumberFormatter::TYPE_INT64));

    // you can change the grouping separator character
    $newChar = '/';
    $this->frmtr->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, $newChar);
    $this->assertEquals($newChar, $this->frmtr->getTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL));

    // but it appears to have no effect on parsing....the newly set grouping character is treated as 'trailing debris'
    $expectedResult = 12;
    $this->assertEquals($expectedResult, $this->frmtr->parse("12/345", NumberFormatter::TYPE_INT64));

    // semi-colon appears not to work at all as a grouping separator
    $newChar = ';';
    $this->frmtr->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, $newChar);
    $this->assertFalse($this->frmtr->parse("12;345", NumberFormatter::TYPE_INT64));

    // it also impacts formatting but in a really odd and unexpected way
    $expectedResult = '12,345.';
    $this->assertEquals($expectedResult, $this->frmtr->format(12345, NumberFormatter::TYPE_INT64));

    // ok, let's set it back to 'normal'
    $this->frmtr->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, ',');

    // you can change whether grouping is used
    $this->frmtr->setAttribute(NumberFormatter::GROUPING_USED, false);

    // now the parser will treat the grouping separator as trailing debris which is OK but unexpected perhaps
    $expectedResult = 12;
    $this->assertEquals($expectedResult, $this->frmtr->parse("12,345", NumberFormatter::TYPE_INT64));

    // and the formatting gets screwed up in a weird way with the grouping separator placed at the end
    $expectedResult = '12345,';
    $this->assertEquals($expectedResult, $this->frmtr->format(12345, NumberFormatter::TYPE_INT64));

}

1 Ответ

1 голос
/ 21 июня 2019

Разделители являются СИМВОЛАМИ, а не АТРИБУТАМИ. См. Predefined constants.

Используйте setSymbol вместо setTextAttribute и получите ожидаемые результаты, например:

$frmtr = new \NumberFormatter('en-US', NumberFormatter::DECIMAL);         
$frmtr->setSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '/');
print $frmtr->format("12345", NumberFormatter::TYPE_INT64) . "\n";
print $frmtr->parse("12/345", NumberFormatter::TYPE_INT64) . "\n";

Выходы:

12/345 
12345
...