diff options
author | Fabio Bas <ctrlaltca@gmail.com> | 2013-09-17 23:24:10 +0200 |
---|---|---|
committer | Fabio Bas <ctrlaltca@gmail.com> | 2013-09-17 23:24:16 +0200 |
commit | c26f4bced87e3208105666e9fcd847d5b29dc6e2 (patch) | |
tree | 4e4d99f806741ae9f6691572015f0c0aeec67650 | |
parent | a8753134c454d9f57620f3c21e8aab0e1275000f (diff) |
NumberFormat: force the use of C locale when formatting numbers. Add some testcases. Fixes #486
-rw-r--r-- | framework/I18N/core/NumberFormat.php | 71 | ||||
-rw-r--r-- | tests/unit/I18N/core/NumberFormatTest.php | 67 |
2 files changed, 102 insertions, 36 deletions
diff --git a/framework/I18N/core/NumberFormat.php b/framework/I18N/core/NumberFormat.php index 25af6846..ded64782 100644 --- a/framework/I18N/core/NumberFormat.php +++ b/framework/I18N/core/NumberFormat.php @@ -115,12 +115,17 @@ class NumberFormat */ function format($number, $pattern='d', $currency='USD', $charset='UTF-8') { + $oldLocale=setLocale(LC_NUMERIC, '0'); + setlocale(LC_NUMERIC, 'C'); + $this->setPattern($pattern); if(strtolower($pattern) == 'p') - $number = $number * 100.0; + $number = $number * 100; + + $string = (string)$number; - $decimal = $this->formatDecimal($number); + $decimal = $this->formatDecimal($string); $integer = $this->formatInteger(abs($number)); if(strlen($decimal)>0) @@ -147,6 +152,8 @@ class NumberFormat $result = str_replace('¤',$symbol, $result); + setlocale(LC_NUMERIC, $oldLocale); + return I18N_toEncoding($result, $charset); } @@ -155,17 +162,17 @@ class NumberFormat * @param string the decimal number in string form. * @return string formatted integer string with grouping */ - protected function formatInteger($number) + protected function formatInteger($string) { - $decimalDigits = $this->formatInfo->DecimalDigits; - $string = (string)intval(round($number,$decimalDigits)); + $string = (string)$string; + $decimalDigits = $this->formatInfo->DecimalDigits; //if not decimal digits, assume 0 decimal points. - //if(is_int($decimalDigits) && $decimalDigits > 0) - // $string = (string)round(floatval($string),$decimalDigits); - //$dp = strpos($string, '.'); - //if(is_int($dp)) - // $string = substr($string, 0, $dp); + if(is_int($decimalDigits) && $decimalDigits > 0) + $string = (string)round(floatval($string),$decimalDigits); + $dp = strpos($string, '.'); + if(is_int($dp)) + $string = substr($string, 0, $dp); $integer = ''; $digitSize = $this->formatInfo->getDigitSize(); @@ -228,23 +235,43 @@ class NumberFormat * @param string the decimal number in string form. * @return string formatted decimal places. */ - protected function formatDecimal($number) + protected function formatDecimal($string) { - $decimalDigits = $this->formatInfo->DecimalDigits; - $decimalSeparator = $this->formatInfo->DecimalSeparator; + $dp = strpos($string, '.'); $decimal = ''; - if ($decimalDigits > 0) { - //do the correct rounding here - $number = round(floatval($number), $decimalDigits); - $decimal = substr((string)$number,strlen((string)intval($number))+1 ); - $decimal = $decimalSeparator.str_pad($decimal,$decimalDigits,'0',STR_PAD_RIGHT); + $decimalDigits = $this->formatInfo->DecimalDigits; + $decimalSeparator = $this->formatInfo->DecimalSeparator; - } elseif($decimalDigits == -1) { - $decimal = $decimalSeparator.substr((string)$number,strlen((string)intval($number))+1 ); - } elseif($decimalDigits == false) - $decimal = $decimalSeparator.substr((string)$number,strlen((string)intval($number))+1 ); + //do the correct rounding here + //$string = round(floatval($string), $decimalDigits); + if(is_int($dp)) + { + if($decimalDigits == -1) + { + $decimal = substr($string, $dp+1); + } + else if(is_int($decimalDigits)) + { + $float = round((float)$string, $decimalDigits); + if(strpos((string)$float, '.') === false) + { + $decimal = str_pad($decimal,$decimalDigits,'0'); + } + else + { + $decimal = substr($float, strpos($float,'.')+1); + if(strlen($decimal)<$decimalDigits) + $decimal = str_pad($decimal,$decimalDigits,'0'); + } + } + else + return $decimal; + return $decimalSeparator.$decimal; + } + else if ($decimalDigits > 0) + return $decimalSeparator.str_pad($decimal,$decimalDigits,'0'); return $decimal; } diff --git a/tests/unit/I18N/core/NumberFormatTest.php b/tests/unit/I18N/core/NumberFormatTest.php index 6a6f2dd0..958f05f4 100644 --- a/tests/unit/I18N/core/NumberFormatTest.php +++ b/tests/unit/I18N/core/NumberFormatTest.php @@ -24,6 +24,7 @@ class NumberFormatTest extends PHPUnit_Framework_TestCase { $fr = new NumberFormat('fr'); $de = new NumberFormat('de'); $ja = new NumberFormat('ja_JP'); + $it = new NumberFormat('it_IT'); $number = '123456789.125156'; @@ -42,6 +43,10 @@ class NumberFormatTest extends PHPUnit_Framework_TestCase { //custom/unkown currency $wanted = 'DLL123,456,789'; $this->assertEquals($wanted, $ja->format($number,'c','DLL')); + + //italian + $wanted = '€ 123.456.789,13'; + $this->assertEquals($wanted, $it->format($number,'c','EUR')); } function testCustomFormat() { @@ -108,24 +113,58 @@ class NumberFormatTest extends PHPUnit_Framework_TestCase { function testRounding() { - $formatter = new NumberFormat(); - - $number = 349.999; - $pattern = '#.00'; - $expected = '350.00'; - - $this->assertEquals($expected, $formatter->format($number, $pattern)); + $formatter = new NumberFormat(); + + $number = 349.999; + $pattern = '#.00'; + $expected = '350.00'; + + $this->assertEquals($expected, $formatter->format($number, $pattern)); } function testRounding2() { - $formatter = new NumberFormat(); - - $number = 349.99; - $pattern = '#.00'; - $expected = '349.99'; - - $this->assertEquals($expected, $formatter->format($number, $pattern)); + $formatter = new NumberFormat(); + + $number = 349.99; + $pattern = '#.00'; + $expected = '349.99'; + + $this->assertEquals($expected, $formatter->format($number, $pattern)); + } + + function testLocalizedCurrencyFormats2() { + + $it = new NumberFormat('it_IT'); + + $number = 12.41; + $wanted = '12,41'; + $this->assertEquals($wanted, $it->format($number,'d')); + + $number = 10.23; + $wanted = '10,23'; + $this->assertEquals($wanted, $it->format($number,'d')); + + $number = 10010.23; + $wanted = '10.010,23'; + $this->assertEquals($wanted, $it->format($number,'d')); + + $old= setlocale(LC_ALL,"0"); + setlocale(LC_ALL,"it_IT"); + + $number = 12.41; + $wanted = '12,41'; + $this->assertEquals($wanted, $it->format($number,'d')); + + $number = 10.23; + $wanted = '10,23'; + $this->assertEquals($wanted, $it->format($number,'d')); + + $number = 10010.23; + $wanted = '10.010,23'; + $this->assertEquals($wanted, $it->format($number,'d')); + + setlocale(LC_ALL,$old); } } |