Skip to content

Commit

Permalink
Merge pull request #14 from pulzarraider/zerofill_fix
Browse files Browse the repository at this point in the history
Fix bug with formatting zero duration
  • Loading branch information
kevinkhill committed Feb 14, 2019
2 parents e8b51ba + 162c2b8 commit 2118a06
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 26 deletions.
41 changes: 21 additions & 20 deletions src/Duration.php
Expand Up @@ -20,38 +20,38 @@ class Duration
/**
* Duration constructor.
*
* @param null $duration
* @param int|float|string|null $duration
*/
public function __construct($duration = null, $hoursPerDay = 24)
{
$this->days = 0;
$this->hours = 0;
$this->minutes = 0;
$this->seconds = 0;
$this->reset();

$this->output = '';
$this->daysRegex = '/([0-9\.]+)\s?(?:d|D)/';
$this->hoursRegex = '/([0-9\.]+)\s?(?:h|H)/';
$this->minutesRegex = '/([0-9]{1,2})\s?(?:m|M)/';
$this->secondsRegex = '/([0-9]{1,2}(\.\d+)?)\s?(?:s|S)/';

$this->hoursPerDay = $hoursPerDay;

if (!is_null($duration)) {
if (null !== $duration) {
$this->parse($duration);
}
}

/**
* Attempt to parse one of the forms of duration.
*
* @param int|float|string $duration A string or number, representing a duration
* @param int|float|string|null $duration A string or number, representing a duration
* @return self|bool returns the Duration object if successful, otherwise false
*/
public function parse($duration)
{
$this->reset();

if (null === $duration) {
return false;
}

if (is_numeric($duration)) {
$this->seconds = (float)$duration;

Expand Down Expand Up @@ -104,13 +104,13 @@ public function parse($duration)
if (preg_match($this->daysRegex, $duration, $matches)) {
$num = $this->numberBreakdown((float) $matches[1]);
$this->days += (int)$num[0];
$this->hours += $num[1] * $this->hoursPerDay;
$this->hours += $num[1] * $this->hoursPerDay;
}

if (preg_match($this->hoursRegex, $duration, $matches)) {
$num = $this->numberBreakdown((float) $matches[1]);
$num = $this->numberBreakdown((float) $matches[1]);
$this->hours += (int)$num[0];
$this->minutes += $num[1] * 60;
$this->minutes += $num[1] * 60;
}

if (preg_match($this->minutesRegex, $duration, $matches)) {
Expand Down Expand Up @@ -138,7 +138,7 @@ public function parse($duration)
*/
public function toSeconds($duration = null, $precision = false)
{
if (!is_null($duration)) {
if (null !== $duration) {
$this->parse($duration);
}
$this->output = ($this->days * $this->hoursPerDay * 60 * 60) + ($this->hours * 60 * 60) + ($this->minutes * 60) + $this->seconds;
Expand All @@ -157,7 +157,7 @@ public function toSeconds($duration = null, $precision = false)
*/
public function toMinutes($duration = null, $precision = false)
{
if (!is_null($duration)) {
if (null !== $duration) {
$this->parse($duration);
}

Expand All @@ -180,14 +180,13 @@ public function toMinutes($duration = null, $precision = false)
* - 42 minutes would be "0:42:00"
* - 28 seconds would be "0:00:28"
*
* @param int|float|string $duration A string or number, representing a duration
* @param int|float|string|null $duration A string or number, representing a duration
* @param bool $zeroFill A boolean, to force zero-fill result or not (see example)
* @return string
*/
public function formatted($duration = null, $zeroFill = false)
{

if (!is_null($duration)) {
if (null !== $duration) {
$this->parse($duration);
}

Expand All @@ -200,8 +199,10 @@ public function formatted($duration = null, $zeroFill = false)
$this->output .= $this->seconds;
}
} else {
if ($this->minutes > 0 || $hours > 0) {
if ($this->minutes > 0 || $hours > 0 || $zeroFill) {
$this->output = '00';
} else {
$this->output = '0';
}
}

Expand Down Expand Up @@ -238,11 +239,11 @@ public function formatted($duration = null, $zeroFill = false)
*/
public function humanize($duration = null)
{
if (!is_null($duration)) {
if (null !== $duration) {
$this->parse($duration);
}

if ($this->seconds > 0) {
if ($this->seconds > 0 || ($this->seconds === 0.0 && $this->minutes === 0 && $this->hours === 0 && $this->days === 0)) {
$this->output .= $this->seconds . 's';
}

Expand Down Expand Up @@ -294,7 +295,7 @@ private function numberBreakdown($number, $returnUnsigned = false)
private function reset()
{
$this->output = '';
$this->seconds = 0;
$this->seconds = 0.0;
$this->minutes = 0;
$this->hours = 0;
$this->days = 0;
Expand Down
32 changes: 26 additions & 6 deletions test/DurationTest.php
Expand Up @@ -14,6 +14,9 @@ public function setUp()
public function secondsSampleData()
{
return array(
array(false, null),
array(false, ' '),
array(0, '0 s'),
array(1, '1 s'),
array(1, '1 sec'),
array(3, '3S'),
Expand All @@ -39,6 +42,7 @@ public function testGettingValueFromSecondSuffixes($expectedSeconds, $secStr)
public function minutesSampleData()
{
return array(
array(0, '0m'),
array(1, '1 m'),
array(4, '4 min'),
array(6, '6M'),
Expand All @@ -61,6 +65,7 @@ public function testGettingValueFromMinuteSuffixes($intVal, $minStr)
public function hoursSampleData()
{
return array(
array(0, '0h'),
array(1, '1 h'),
array(1, '1 hr'),
array(1, '1H'),
Expand All @@ -84,6 +89,7 @@ public function testGettingValueFromHourSuffixes($intVal, $hrStr)
public function daysSampleData()
{
return array(
array(0, '0d'),
array(1, '1 d'),
array(1, '1 D'),
array(1, '1D'),
Expand All @@ -106,6 +112,7 @@ public function testGettingValueFromDaySuffixes($intVal, $dayStr)

public function testConvertingSecondsToFormattedString()
{
$this->assertEquals('0', $this->d->formatted(0));
$this->assertEquals('4', $this->d->formatted(4));
$this->assertEquals('9', $this->d->formatted(9));
$this->assertEquals('42', $this->d->formatted(42));
Expand All @@ -122,6 +129,7 @@ public function testConvertingSecondsToFormattedString()
$this->assertEquals('1:09:09', $this->d->formatted(4149));

// microseconds
$this->assertEquals('0.0', $this->d->formatted(0.0));
$this->assertEquals('4.987', $this->d->formatted(4.987));
$this->assertEquals('9.123', $this->d->formatted(9.123));
$this->assertEquals('42.672', $this->d->formatted(42.672));
Expand All @@ -140,6 +148,7 @@ public function testConvertingSecondsToFormattedString()

public function testConvertingSecondsToFormattedStringZeroFilled()
{
$this->assertEquals('0:00:00', $this->d->formatted(0, true));
$this->assertEquals('0:00:04', $this->d->formatted(4, true));
$this->assertEquals('0:00:09', $this->d->formatted(9, true));
$this->assertEquals('0:00:42', $this->d->formatted(42, true));
Expand All @@ -162,6 +171,7 @@ public function testConvertingSecondsToFormattedStringZeroFilled()

public function testConvertingFormattedStringsToSeconds()
{
$this->assertEquals(0, $this->d->toSeconds('0'));
$this->assertEquals(4, $this->d->toSeconds('4'));
$this->assertEquals(9, $this->d->toSeconds('9'));
$this->assertEquals(42, $this->d->toSeconds('42'));
Expand Down Expand Up @@ -194,6 +204,7 @@ public function testConvertingFormattedStringsToSeconds()
$this->assertEquals(4149.499999, $this->d->toSeconds('1:09:09.499999'));

// precision
$this->assertEquals(0, $this->d->toSeconds('0', 0));
$this->assertEquals(5, $this->d->toSeconds('4.6', 0));
$this->assertEquals(10, $this->d->toSeconds('9.5', 0));
$this->assertEquals(42.1, $this->d->toSeconds('42.1', 1));
Expand All @@ -212,6 +223,7 @@ public function testConvertingFormattedStringsToSeconds()

public function testConvertingFormattedStringsToMinutes()
{
$this->assertEquals(0, $this->d->toMinutes('0'));
$this->assertEquals(4 / 60, $this->d->toMinutes('4'));
$this->assertEquals(9 / 60, $this->d->toMinutes('9'));
$this->assertEquals(42 / 60, $this->d->toMinutes('42'));
Expand All @@ -228,6 +240,7 @@ public function testConvertingFormattedStringsToMinutes()
$this->assertEquals(4149 / 60, $this->d->toMinutes('1:09:09'));

// to integer - BC
$this->assertEquals(0, $this->d->toMinutes('0', true));
$this->assertEquals(0, $this->d->toMinutes('4', true));
$this->assertEquals(0, $this->d->toMinutes('9', true));
$this->assertEquals(1, $this->d->toMinutes('42', true));
Expand All @@ -245,6 +258,7 @@ public function testConvertingFormattedStringsToMinutes()
$this->assertEquals(69, $this->d->toMinutes('1:09:09', true));

// precision
$this->assertEquals(0, $this->d->toMinutes('0', 0));
$this->assertEquals(0, $this->d->toMinutes('4', 0));
$this->assertEquals(0, $this->d->toMinutes('9', 0));
$this->assertEquals(1, $this->d->toMinutes('42', 0));
Expand All @@ -261,6 +275,7 @@ public function testConvertingFormattedStringsToMinutes()
$this->assertEquals(65, $this->d->toMinutes('1:04:55', 0));
$this->assertEquals(69, $this->d->toMinutes('1:09:09', 0));

$this->assertEquals(0, $this->d->toMinutes('0', 1));
$this->assertEquals(0.1, $this->d->toMinutes('4', 1));
$this->assertEquals(0.15, $this->d->toMinutes('9', 2));
$this->assertEquals(0.7, $this->d->toMinutes('42', 3));
Expand All @@ -280,6 +295,7 @@ public function testConvertingFormattedStringsToMinutes()

public function testConvertSecondsToHumanizedString()
{
$this->assertEquals('0s', $this->d->humanize(0));
$this->assertEquals('4s', $this->d->humanize(4));
$this->assertEquals('42s', $this->d->humanize(42));
$this->assertEquals('1m 2s', $this->d->humanize(62));
Expand All @@ -304,6 +320,7 @@ public function testConvertSecondsToHumanizedString()
*/
public function testConvertHumanizedStringToSeconds()
{
$this->assertEquals(0, $this->d->toSeconds('0s'));
$this->assertEquals(4, $this->d->toSeconds('4s'));
$this->assertEquals(42, $this->d->toSeconds('42s'));
$this->assertEquals(72, $this->d->toSeconds('1m 12s'));
Expand All @@ -321,30 +338,33 @@ public function testConvertHumanizedStringToSeconds()
public function testConvertHumanizedStringToSeconds7HourDay()
{
$d = new Duration(null, 7);

$this->assertEquals(0, $d->toSeconds('0d'));
$this->assertEquals(25200, $d->toSeconds('1d'));
$this->assertEquals(91800, $d->toSeconds('2d 11h 30m'));
}

public function testSupportDecimals()
{
$d = new Duration(null, 6);


$this->assertEquals(0, $d->toMinutes('0d'));
$this->assertEquals(6 * 60, $d->toMinutes('1d'));
$this->assertEquals((6 + 3) * 60, $d->toMinutes('1.5d'));
$this->assertEquals(60, $d->toMinutes('1h'));
$this->assertEquals(60 + 30, $d->toMinutes('1.5h'));
$this->assertEquals((12 * 60) + 60 + 30, $d->toMinutes('2d 1.5h'));
$this->assertEquals((12 * 60) + 60 + 30, $d->toMinutes('2d 1.5h'));
}

public function testConvertHumanizedWithSupportDecimals()
{
$t = '1.5d 1.5h 2m 5s';
$t = '1.5d 1.5h 2m 5s';

$this->assertEquals('1d 4h 32m 5s', (new Duration($t, 6))->humanize(), "Test humanize with: {$t}");
$this->assertEquals('10:32:05', (new Duration($t, 6))->formatted(), "Test formatted with: {$t}");
$this->assertEquals(37925, (new Duration($t, 6))->toSeconds(), "Test toSeconds with: {$t}");
$this->assertEquals(37925/60, (new Duration($t, 6))->toMinutes(), "Test toMinutes with: {$t}");
$this->assertEquals(632, (new Duration($t, 6))->toMinutes(null, 0), "Test toMinutes with: {$t}");
}
$this->assertEquals(632, (new Duration($t, 6))->toMinutes(null, 0), "Test toMinutes with: {$t}");
}

}

0 comments on commit 2118a06

Please sign in to comment.