diff --git a/README.md b/README.md index ecd2515..b94df81 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,8 @@ echo Number::fromRoman("CXXV"); // 125 **Binary Suffix** +Convert a number of bytes in to the highest applicable data unit + ```php use Coduo\PHPHumanizer\Number; @@ -128,6 +130,24 @@ use Coduo\PHPHumanizer\Number; echo Number::binarySuffix(1536, 'pl'); // "1,5 kB" ``` +Number can also be humanized with a specific number of decimal places with `preciseBinarySuffix($number, $precision, $locale = 'en')` +The precision parameter must be between 0 and 3. + +```php +use Coduo\PHPHumanizer\Number; + +echo Number::preciseBinarySuffix(1024, 2); // "1.00 kB" +echo Number::preciseBinarySuffix(1325899906842624, 3); // "1.178 PB" +``` + +This function also supports locale + +```php +use Coduo\PHPHumanizer\Number; + +echo Number::preciseBinarySuffix(1325899906842624, 3, 'pl'); // "1,178 PB" +``` + **Metric Suffix** ```php diff --git a/src/Coduo/PHPHumanizer/Number.php b/src/Coduo/PHPHumanizer/Number.php index b354f53..89caf87 100644 --- a/src/Coduo/PHPHumanizer/Number.php +++ b/src/Coduo/PHPHumanizer/Number.php @@ -26,6 +26,13 @@ public static function binarySuffix($number, $locale = 'en') return $binarySuffix->convert(); } + public static function preciseBinarySuffix($number, $precision, $locale = 'en') + { + $binarySuffix = new BinarySuffix($number, $locale, $precision); + + return $binarySuffix->convert(); + } + public static function metricSuffix($number, $locale = 'en') { $binarySuffix = new MetricSuffix($number, $locale); diff --git a/src/Coduo/PHPHumanizer/String/BinarySuffix.php b/src/Coduo/PHPHumanizer/String/BinarySuffix.php index 446f642..ab6ac36 100644 --- a/src/Coduo/PHPHumanizer/String/BinarySuffix.php +++ b/src/Coduo/PHPHumanizer/String/BinarySuffix.php @@ -29,21 +29,57 @@ class BinarySuffix ); /** - * @param $number - * @param string $locale + * @param integer $number + * @param string $locale + * @param integer $precision * * @throws \InvalidArgumentException */ - public function __construct($number, $locale = 'en') + public function __construct($number, $locale = 'en', $precision = null) { if (!is_numeric($number)) { throw new \InvalidArgumentException('Binary suffix converter accept only numeric values.'); } + if(!is_null($precision)){ + $this->setSpecificPrecisionFormat($precision); + } + $this->number = (int) $number; $this->locale = $locale; } + /** + * Replaces the default ICU 56.1 decimal formats defined in $binaryPrefixes with ones that provide the same symbols + * but the provided number of decimal places + * + * @param integer $precision + * + * @throws \InvalidArgumentException + */ + protected function setSpecificPrecisionFormat($precision) + { + if($precision < 0){ + throw new \InvalidArgumentException('Precision must be positive'); + } + if($precision > 3){ + throw new \InvalidArgumentException('Invalid precision. Binary suffix converter can only represent values in '. + 'up to three decimal places'); + } + + $icuFormat = '#'; + if($precision > 0){ + $icuFormat .= str_pad('#.', (2+$precision), '0'); + } + + foreach ($this->binaryPrefixes as $size => $unitPattern) { + if($size >= 1024){ + $symbol = substr($unitPattern, strpos($unitPattern, ' ')); + $this->binaryPrefixes[$size] = $icuFormat.$symbol; + } + } + } + public function convert() { $formatter = new \NumberFormatter($this->locale, \NumberFormatter::PATTERN_DECIMAL); diff --git a/tests/Coduo/PHPHumanizer/Tests/NumberTest.php b/tests/Coduo/PHPHumanizer/Tests/NumberTest.php index a8ca40c..db31d65 100644 --- a/tests/Coduo/PHPHumanizer/Tests/NumberTest.php +++ b/tests/Coduo/PHPHumanizer/Tests/NumberTest.php @@ -49,6 +49,35 @@ public function test_statically_throw_exception_when_converting_to_string_with_b Number::binarySuffix('as12'); } + /** + * @dataProvider preciseBinarySuffixDataProvider + * + * @param $expected + * @param $number + * @param string $locale + * @param integer $precision + */ + public function test_convert_number_to_string_with_precise_binary_suffix($expected, $number, $precision, $locale = 'en') + { + $this->assertEquals($expected, Number::preciseBinarySuffix($number, $precision, $locale)); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function test_statically_throw_exception_when_converting_to_string_with_precise_binary_suffix_negative_precision() + { + Number::preciseBinarySuffix(1, -1); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function test_statically_throw_exception_when_converting_to_string_with_precise_binary_suffix_large_precision() + { + Number::preciseBinarySuffix(1, 4); + } + /** * @dataProvider metricSuffixDataProvider * @@ -163,6 +192,48 @@ public function binarySuffixDataProvider() ); } + /** + * @return array + */ + public function preciseBinarySuffixDataProvider() + { + return array( + // Negative case + array(-1, -1, 3), + + // Byte Cases + array("0 bytes", 0, 3), + array("1 bytes", 1, 0), + array("1023 bytes", 1023, 3), + + // Kilobyte Cases + array('1.000 kB', 1024, 3), + array("2 kB", 1588, 0), + array("1.6 kB", 1588, 1), + array("1.55 kB", 1588, 2), + array("1.551 kB", 1588, 3), + + // Megabyte Cases + array("5.00 MB", (1048576 * 5), 2), + array("5.00 MB", (1048576 * 5) + 600, 2), + array("5.001 MB", (1048576 * 5) + 600, 3), + + // Gigabyte Cases + array("2 GB", 1073741824 * 2, 0), + array("2.0 GB", 1073741824 * 2, 1), + + // Terabyte Cases + array("3.00 TB", 1099511627776 * 3, 2), + + // Petabyte Case + array("1.178 PB", 1325899906842624, 3), + + // Locale Cases + array("1,500 kB", 1536, 3, 'pl'), + array("1,178 PB", 1325899906842624, 3, 'pl'), + ); + } + /** * @return array */