Minor Fix for Percentage Formatting (#3053)

Fix #1929. This was already substantially fixed, but there was a lingering problem with an unexpected leading space. It turns out there was also a problem with leading zeros, also fixed. There are also problems involving commas; fixing those seems too complicated to delay these changes, but I will add it to my to-do list.
This commit is contained in:
oleibman 2022-09-12 08:45:13 -07:00 committed by GitHub
parent 2fe66d097f
commit 3e8d50547c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 8 deletions

View File

@ -20,7 +20,8 @@ class PercentageFormatter extends BaseFormatter
$format = str_replace('%', '%%', $format); $format = str_replace('%', '%%', $format);
$wholePartSize = strlen((string) floor($value)); $wholePartSize = strlen((string) floor($value));
$decimalPartSize = $placeHolders = 0; $decimalPartSize = 0;
$placeHolders = '';
// Number of decimals // Number of decimals
if (preg_match('/\.([?0]+)/u', $format, $matches)) { if (preg_match('/\.([?0]+)/u', $format, $matches)) {
$decimalPartSize = strlen($matches[1]); $decimalPartSize = strlen($matches[1]);
@ -29,12 +30,13 @@ class PercentageFormatter extends BaseFormatter
$placeHolders = str_repeat(' ', strlen($matches[1]) - $decimalPartSize); $placeHolders = str_repeat(' ', strlen($matches[1]) - $decimalPartSize);
} }
// Number of digits to display before the decimal // Number of digits to display before the decimal
if (preg_match('/([#0,]+)\./u', $format, $matches)) { if (preg_match('/([#0,]+)\.?/u', $format, $matches)) {
$wholePartSize = max($wholePartSize, strlen($matches[1])); $firstZero = preg_replace('/^[#,]*/', '', $matches[1]);
$wholePartSize = max($wholePartSize, strlen($firstZero));
} }
$wholePartSize += $decimalPartSize; $wholePartSize += $decimalPartSize + (int) ($decimalPartSize > 0);
$replacement = "{$wholePartSize}.{$decimalPartSize}"; $replacement = "0{$wholePartSize}.{$decimalPartSize}";
$mask = (string) preg_replace('/[#0,]+\.?[?#0,]*/ui', "%{$replacement}f{$placeHolders}", $format); $mask = (string) preg_replace('/[#0,]+\.?[?#0,]*/ui', "%{$replacement}f{$placeHolders}", $format);
/** @var float */ /** @var float */

View File

@ -47,7 +47,7 @@ class NumberFormatTest extends TestCase
public function testFormatValueWithMask($expectedResult, ...$args): void public function testFormatValueWithMask($expectedResult, ...$args): void
{ {
$result = NumberFormat::toFormattedString(...$args); $result = NumberFormat::toFormattedString(...$args);
self::assertEquals($expectedResult, $result); self::assertSame($expectedResult, $result);
} }
public function providerNumberFormat(): array public function providerNumberFormat(): array

View File

@ -146,13 +146,13 @@ return [
'#,###', '#,###',
], ],
[ [
12, '12',
12000, 12000,
'#,', '#,',
], ],
// Scaling test // Scaling test
[ [
12.199999999999999, '12.2',
12200000, 12200000,
'0.0,,', '0.0,,',
], ],
@ -1486,4 +1486,9 @@ return [
'-1111.119', '-1111.119',
NumberFormat::FORMAT_ACCOUNTING_EUR, NumberFormat::FORMAT_ACCOUNTING_EUR,
], ],
'issue 1929' => ['(79.3%)', -0.793, '#,##0.0%;(#,##0.0%)'],
'percent without leading 0' => ['6.2%', 0.062, '##.0%'],
'percent with leading 0' => ['06.2%', 0.062, '00.0%'],
'percent lead0 no decimal' => ['06%', 0.062, '00%'],
'percent nolead0 no decimal' => ['6%', 0.062, '##%'],
]; ];