Skip to content

Commit

Permalink
Merge pull request #12 from pulzarraider/microseconds
Browse files Browse the repository at this point in the history
Add support for microseconds
  • Loading branch information
kevinkhill authored Jul 5, 2018
2 parents 3cfb947 + 50400de commit 5efcb6d
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 139 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ The library can accept either in colon separated format, like 2:43 for 2 minutes
OR
written as human readable or abbreviated time, such as 6m21s for 6 minutes and 21 seconds.

Both can be converted into seconds and minutes for easy storage into a database.
Both can be converted into seconds and minutes with precision for easy storage into a database.

Seconds, colon separated, abbreviated, all three can be parsed and interchanged.
- supports hours, minutes, and seconds
- supports hours, minutes, and seconds (with microseconds)
- humanized input supports any form of the words "hour", "minute", "seconds"
- Example, you could input 1h4m2s or 4 Hr. 32 Min.

Expand All @@ -40,7 +40,8 @@ echo $duration->humanize(); // 7m 31s
echo $duration->formatted(); // 7:31
echo $duration->toSeconds(); // 451
echo $duration->toMinutes(); // 7.5166
echo $duration->toMinutes(null, true); // 8
echo $duration->toMinutes(null, 0); // 8
echo $duration->toMinutes(null, 2); // 7.52
```

```php
Expand All @@ -50,7 +51,7 @@ echo $duration->humanize(); // 1h 2m 5s
echo $duration->formatted(); // 1:02:05
echo $duration->toSeconds(); // 3725
echo $duration->toMinutes(); // 62.0833
echo $duration->toMinutes(null, true); // 62
echo $duration->toMinutes(null, 0); // 62
```

```php
Expand All @@ -60,7 +61,7 @@ echo $duration->humanize(); // 1h 11m 33s
echo $duration->formatted(); // 1:11:33
echo $duration->toSeconds(); // 4293
echo $duration->toMinutes(); // 71.55
echo $duration->toMinutes(null, true); // 72
echo $duration->toMinutes(null, 0); // 72
```

# Note
Expand Down
127 changes: 71 additions & 56 deletions src/Duration.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,140 +17,155 @@ class Duration
private $minutesRegex;
private $secondsRegex;


/**
* Duration constructor.
*
* @param null $duration
*/
public function __construct($duration = null, $hoursPerDay = 24)
{
$this->days = 0;
$this->hours = 0;
$this->days = 0;
$this->hours = 0;
$this->minutes = 0;
$this->seconds = 0;

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

$this->hoursPerDay = $hoursPerDay;

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

/**
* Attempt to parse one of the forms of duration.
*
* @param int|string $duration A string or number, representing a duration
* @param int|float|string $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 (is_numeric($duration)) {
$this->seconds = (int) $duration;
$this->seconds = (float)$duration;

if ($this->seconds >= 60) {
$this->minutes = (int) floor($this->seconds / 60);
$this->seconds = (int) ($this->seconds - ($this->minutes * 60));
$this->minutes = (int)floor($this->seconds / 60);

// count current precision
$precision = 0;
if (($delimiterPos = strpos($this->seconds, '.')) !== false) {
$precision = strlen(substr($this->seconds, $delimiterPos + 1));
}

$this->seconds = (float)round(($this->seconds - ($this->minutes * 60)), $precision);
}

if ($this->minutes >= 60) {
$this->hours = (int) floor($this->minutes / 60);
$this->minutes = (int) ($this->minutes - ($this->hours * 60));
$this->hours = (int)floor($this->minutes / 60);
$this->minutes = (int)($this->minutes - ($this->hours * 60));
}

if ($this->hours >= $this->hoursPerDay) {
$this->days = (int) floor($this->hours / $this->hoursPerDay);
$this->hours = (int) ($this->hours - ($this->days * $this->hoursPerDay));
$this->days = (int)floor($this->hours / $this->hoursPerDay);
$this->hours = (int)($this->hours - ($this->days * $this->hoursPerDay));
}

return $this;
} else if (preg_match('/\:/', $duration)) {
}

if (preg_match('/\:/', $duration)) {
$parts = explode(':', $duration);

if (count($parts) == 2) {
$this->minutes = (int) $parts[0];
$this->seconds = (int) $parts[1];
} else if (count($parts) == 3) {
$this->hours = (int) $parts[0];
$this->minutes = (int) $parts[1];
$this->seconds = (int) $parts[2];
$this->minutes = (int)$parts[0];
$this->seconds = (float)$parts[1];
} else {
if (count($parts) == 3) {
$this->hours = (int)$parts[0];
$this->minutes = (int)$parts[1];
$this->seconds = (float)$parts[2];
}
}

return $this;
} else if (preg_match($this->daysRegex, $duration) ||
preg_match($this->hoursRegex, $duration) ||
preg_match($this->minutesRegex, $duration) ||
preg_match($this->secondsRegex, $duration))
{
}

if (preg_match($this->daysRegex, $duration) ||
preg_match($this->hoursRegex, $duration) ||
preg_match($this->minutesRegex, $duration) ||
preg_match($this->secondsRegex, $duration)) {
if (preg_match($this->daysRegex, $duration, $matches)) {
$this->days = (int) $matches[1];
$this->days = (int)$matches[1];
}

if (preg_match($this->hoursRegex, $duration, $matches)) {
$this->hours = (int) $matches[1];
$this->hours = (int)$matches[1];
}

if (preg_match($this->minutesRegex, $duration, $matches)) {
$this->minutes = (int) $matches[1];
$this->minutes = (int)$matches[1];
}

if (preg_match($this->secondsRegex, $duration, $matches)) {
$this->seconds = (int) $matches[1];
$this->seconds = (float)$matches[1];
}

return $this;
} else {
return false;
}

return false;
}

/**
* Returns the duration as an amount of seconds.
*
* For example, one hour and 42 minutes would be "6120"
*
* @param int|string $duration A string or number, representing a duration
* @return int
* @param int|float|string $duration A string or number, representing a duration
* @param int|bool $precision Number of decimal digits to round to. If set to false, the number is not rounded.
* @return int|float
*/
public function toSeconds($duration = null)
public function toSeconds($duration = null, $precision = false)
{
if (! is_null($duration)) {
if (!is_null($duration)) {
$this->parse($duration);
}

$this->output = ($this->days * $this->hoursPerDay * 60 * 60) + ($this->hours * 60 * 60) + ($this->minutes * 60) + $this->seconds;

return (int) $this->output();
return $precision !== false ? round($this->output, $precision) : $this->output;
}

/**
* Returns the duration as an amount of seconds.
* Returns the duration as an amount of minutes.
*
* For example, one hour and 42 minutes would be "102" minutes
*
* @param int|string $duration A string or number, representing a duration
* @param boolean $roundToInteger Should the number be rounded and returned as integer
* @return int
* @param int|float|string $duration A string or number, representing a duration
* @param int|bool $precision Number of decimal digits to round to. If set to false, the number is not rounded.
* @return int|float
*/
public function toMinutes($duration = null, $roundToInteger = false)
public function toMinutes($duration = null, $precision = false)
{
if (! is_null($duration)) {
if (!is_null($duration)) {
$this->parse($duration);
}

// backward compatibility, true = round to integer
if ($precision === true) {
$precision = 0;
}

$this->output = ($this->days * $this->hoursPerDay * 60 * 60) + ($this->hours * 60 * 60) + ($this->minutes * 60) + $this->seconds;
$result = intval($this->output()) / 60;

return $roundToInteger ? intval(round($result, 0)) : $result;
return $precision !== false ? round($result, $precision) : $result;
}

/**
Expand All @@ -161,21 +176,21 @@ public function toMinutes($duration = null, $roundToInteger = false)
* - 42 minutes would be "0:42:00"
* - 28 seconds would be "0:00:28"
*
* @param int|string $duration A string or number, representing a duration
* @param int|float|string $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 (!is_null($duration)) {
$this->parse($duration);
}

$hours = $this->hours + ($this->days * $this->hoursPerDay);

if ($this->seconds > 0) {
if ($this->seconds <= 9 && ($this->minutes > 0 || $hours > 0 || $zeroFill)) {
if ($this->seconds > 0) {
if ($this->seconds < 10 && ($this->minutes > 0 || $hours > 0 || $zeroFill)) {
$this->output .= '0' . $this->seconds;
} else {
$this->output .= $this->seconds;
Expand Down Expand Up @@ -214,12 +229,12 @@ public function formatted($duration = null, $zeroFill = false)
*
* For example, one hour and 42 minutes would be "1h 42m"
*
* @param int|string $duration A string or number, representing a duration
* @param int|float|string $duration A string or number, representing a duration
* @return string
*/
public function humanize($duration = null)
{
if (! is_null($duration)) {
if (!is_null($duration)) {
$this->parse($duration);
}

Expand Down Expand Up @@ -251,11 +266,11 @@ public function humanize($duration = null)
*/
private function reset()
{
$this->output = '';
$this->output = '';
$this->seconds = 0;
$this->minutes = 0;
$this->hours = 0;
$this->days = 0;
$this->hours = 0;
$this->days = 0;
}

/**
Expand Down
Loading

0 comments on commit 5efcb6d

Please sign in to comment.