Browse Source

Add option to set rounding mode for I18n numbers

Adam Halfar 2 years ago
parent
commit
09697dd461
3 changed files with 29 additions and 0 deletions
  1. 8 0
      src/I18n/Number.php
  2. 2 0
      src/View/Helper/NumberHelper.php
  3. 19 0
      tests/TestCase/I18n/NumberTest.php

+ 8 - 0
src/I18n/Number.php

@@ -217,6 +217,8 @@ class Number
      * - `zero` - The text to use for zero values, can be a string or a number. e.g. 0, 'Free!'
      * - `places` - Number of decimal places to use. e.g. 2
      * - `precision` - Maximum Number of decimal places to use, e.g. 2
+     * - `roundingMode` - Rounding mode to use. e.g. NumberFormatter::ROUND_HALF_UP.
+     *   When not set locale default will be used
      * - `pattern` - An ICU number pattern to use for formatting the number. e.g #,##0.00
      * - `useIntlCode` - Whether to replace the currency symbol with the international
      *   currency code.
@@ -317,6 +319,8 @@ class Number
      *    numbers representing money or a NumberFormatter constant.
      * - `places` - Number of decimal places to use. e.g. 2
      * - `precision` - Maximum Number of decimal places to use, e.g. 2
+     * - `roundingMode` - Rounding mode to use. e.g. NumberFormatter::ROUND_HALF_UP.
+     *   When not set locale default will be used
      * - `pattern` - An ICU number pattern to use for formatting the number. e.g #,##0.00
      * - `useIntlCode` - Whether to replace the currency symbol with the international
      *   currency code.
@@ -387,6 +391,10 @@ class Number
             $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $options['precision']);
         }
 
+        if (isset($options['roundingMode'])) {
+            $formatter->setAttribute(NumberFormatter::ROUNDING_MODE, $options['roundingMode']);
+        }
+
         if (!empty($options['pattern'])) {
             $formatter->setPattern($options['pattern']);
         }

+ 2 - 0
src/View/Helper/NumberHelper.php

@@ -85,6 +85,8 @@ class NumberHelper extends Helper
      * - `zero` - The text to use for zero values, can be a string or a number. e.g. 0, 'Free!'
      * - `places` - Number of decimal places to use. e.g. 2
      * - `precision` - Maximum Number of decimal places to use, e.g. 2
+     * - `roundingMode` - Rounding mode to use. e.g. NumberFormatter::ROUND_HALF_UP.
+     *   When not set locale default will be used
      * - `pattern` - An ICU number pattern to use for formatting the number. e.g #,##0.00
      * - `useIntlCode` - Whether to replace the currency symbol with the international
      *   currency code.

+ 19 - 0
tests/TestCase/I18n/NumberTest.php

@@ -92,6 +92,17 @@ class NumberTest extends TestCase
         $result = $this->Number->format($value, $options);
         $expected = '1,23 €';
         $this->assertSame($expected, $result);
+
+        $value = 1.665;
+        $options = ['locale' => 'cs_CZ', 'precision' => 2];
+        $result = $this->Number->format($value, $options);
+        $expected = '1,66';
+        $this->assertSame($expected, $result);
+
+        $options = ['locale' => 'cs_CZ', 'precision' => 2, 'roundingMode' => NumberFormatter::ROUND_HALFUP];
+        $result = $this->Number->format($value, $options);
+        $expected = '1,67';
+        $this->assertSame($expected, $result);
     }
 
     /**
@@ -283,6 +294,14 @@ class NumberTest extends TestCase
         $expected = '1,230 €';
         $this->assertSame($expected, $result);
 
+        $result = $this->Number->currency('1.665', 'CZK', ['locale' => 'cs_CZ', 'places' => 2]);
+        $expected = '1,66 Kč';
+        $this->assertSame($expected, $result);
+
+        $result = $this->Number->currency('1.665', 'CZK', ['locale' => 'cs_CZ', 'places' => 2, 'roundingMode' => NumberFormatter::ROUND_HALFUP]);
+        $expected = '1,67 Kč';
+        $this->assertSame($expected, $result);
+
         $result = $this->Number->currency('0.23', 'GBP', ['places' => 3, 'fractionSymbol' => 'p']);
         $expected = '23p';
         $this->assertSame($expected, $result);