Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for optional explicit BinarySuffix precision #47

Merged
merged 10 commits into from
Nov 5, 2015
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/Coduo/PHPHumanizer/Number.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
42 changes: 39 additions & 3 deletions src/Coduo/PHPHumanizer/String/BinarySuffix.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
71 changes: 71 additions & 0 deletions tests/Coduo/PHPHumanizer/Tests/NumberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add some tests for precision that is bigger and lower than 3? For example, 1,2,3,4,5,6,7 ?


// Locale Cases
array("1,500 kB", 1536, 3, 'pl'),
array("1,178 PB", 1325899906842624, 3, 'pl'),
);
}

/**
* @return array
*/
Expand Down