summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabio Bas <ctrlaltca@gmail.com>2013-09-17 23:24:10 +0200
committerFabio Bas <ctrlaltca@gmail.com>2013-09-17 23:24:16 +0200
commitc26f4bced87e3208105666e9fcd847d5b29dc6e2 (patch)
tree4e4d99f806741ae9f6691572015f0c0aeec67650
parenta8753134c454d9f57620f3c21e8aab0e1275000f (diff)
NumberFormat: force the use of C locale when formatting numbers. Add some testcases. Fixes #486
-rw-r--r--framework/I18N/core/NumberFormat.php71
-rw-r--r--tests/unit/I18N/core/NumberFormatTest.php67
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);
}
}