Skip to content

Commit 5efcb6d

Browse files
authored
Merge pull request #12 from pulzarraider/microseconds
Add support for microseconds
2 parents 3cfb947 + 50400de commit 5efcb6d

File tree

3 files changed

+247
-139
lines changed

3 files changed

+247
-139
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ The library can accept either in colon separated format, like 2:43 for 2 minutes
1515
OR
1616
written as human readable or abbreviated time, such as 6m21s for 6 minutes and 21 seconds.
1717

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

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

@@ -40,7 +40,8 @@ echo $duration->humanize(); // 7m 31s
4040
echo $duration->formatted(); // 7:31
4141
echo $duration->toSeconds(); // 451
4242
echo $duration->toMinutes(); // 7.5166
43-
echo $duration->toMinutes(null, true); // 8
43+
echo $duration->toMinutes(null, 0); // 8
44+
echo $duration->toMinutes(null, 2); // 7.52
4445
```
4546

4647
```php
@@ -50,7 +51,7 @@ echo $duration->humanize(); // 1h 2m 5s
5051
echo $duration->formatted(); // 1:02:05
5152
echo $duration->toSeconds(); // 3725
5253
echo $duration->toMinutes(); // 62.0833
53-
echo $duration->toMinutes(null, true); // 62
54+
echo $duration->toMinutes(null, 0); // 62
5455
```
5556

5657
```php
@@ -60,7 +61,7 @@ echo $duration->humanize(); // 1h 11m 33s
6061
echo $duration->formatted(); // 1:11:33
6162
echo $duration->toSeconds(); // 4293
6263
echo $duration->toMinutes(); // 71.55
63-
echo $duration->toMinutes(null, true); // 72
64+
echo $duration->toMinutes(null, 0); // 72
6465
```
6566

6667
# Note

src/Duration.php

Lines changed: 71 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -17,140 +17,155 @@ class Duration
1717
private $minutesRegex;
1818
private $secondsRegex;
1919

20-
2120
/**
2221
* Duration constructor.
2322
*
2423
* @param null $duration
2524
*/
2625
public function __construct($duration = null, $hoursPerDay = 24)
2726
{
28-
$this->days = 0;
29-
$this->hours = 0;
27+
$this->days = 0;
28+
$this->hours = 0;
3029
$this->minutes = 0;
3130
$this->seconds = 0;
3231

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

3938
$this->hoursPerDay = $hoursPerDay;
4039

41-
if (! is_null($duration)) {
40+
if (!is_null($duration)) {
4241
$this->parse($duration);
4342
}
4443
}
4544

4645
/**
4746
* Attempt to parse one of the forms of duration.
4847
*
49-
* @param int|string $duration A string or number, representing a duration
48+
* @param int|float|string $duration A string or number, representing a duration
5049
* @return self|bool returns the Duration object if successful, otherwise false
5150
*/
5251
public function parse($duration)
5352
{
5453
$this->reset();
5554

5655
if (is_numeric($duration)) {
57-
$this->seconds = (int) $duration;
56+
$this->seconds = (float)$duration;
5857

5958
if ($this->seconds >= 60) {
60-
$this->minutes = (int) floor($this->seconds / 60);
61-
$this->seconds = (int) ($this->seconds - ($this->minutes * 60));
59+
$this->minutes = (int)floor($this->seconds / 60);
60+
61+
// count current precision
62+
$precision = 0;
63+
if (($delimiterPos = strpos($this->seconds, '.')) !== false) {
64+
$precision = strlen(substr($this->seconds, $delimiterPos + 1));
65+
}
66+
67+
$this->seconds = (float)round(($this->seconds - ($this->minutes * 60)), $precision);
6268
}
6369

6470
if ($this->minutes >= 60) {
65-
$this->hours = (int) floor($this->minutes / 60);
66-
$this->minutes = (int) ($this->minutes - ($this->hours * 60));
71+
$this->hours = (int)floor($this->minutes / 60);
72+
$this->minutes = (int)($this->minutes - ($this->hours * 60));
6773
}
6874

6975
if ($this->hours >= $this->hoursPerDay) {
70-
$this->days = (int) floor($this->hours / $this->hoursPerDay);
71-
$this->hours = (int) ($this->hours - ($this->days * $this->hoursPerDay));
76+
$this->days = (int)floor($this->hours / $this->hoursPerDay);
77+
$this->hours = (int)($this->hours - ($this->days * $this->hoursPerDay));
7278
}
7379

7480
return $this;
75-
} else if (preg_match('/\:/', $duration)) {
81+
}
82+
83+
if (preg_match('/\:/', $duration)) {
7684
$parts = explode(':', $duration);
7785

7886
if (count($parts) == 2) {
79-
$this->minutes = (int) $parts[0];
80-
$this->seconds = (int) $parts[1];
81-
} else if (count($parts) == 3) {
82-
$this->hours = (int) $parts[0];
83-
$this->minutes = (int) $parts[1];
84-
$this->seconds = (int) $parts[2];
87+
$this->minutes = (int)$parts[0];
88+
$this->seconds = (float)$parts[1];
89+
} else {
90+
if (count($parts) == 3) {
91+
$this->hours = (int)$parts[0];
92+
$this->minutes = (int)$parts[1];
93+
$this->seconds = (float)$parts[2];
94+
}
8595
}
8696

8797
return $this;
88-
} else if (preg_match($this->daysRegex, $duration) ||
89-
preg_match($this->hoursRegex, $duration) ||
90-
preg_match($this->minutesRegex, $duration) ||
91-
preg_match($this->secondsRegex, $duration))
92-
{
98+
}
9399

100+
if (preg_match($this->daysRegex, $duration) ||
101+
preg_match($this->hoursRegex, $duration) ||
102+
preg_match($this->minutesRegex, $duration) ||
103+
preg_match($this->secondsRegex, $duration)) {
94104
if (preg_match($this->daysRegex, $duration, $matches)) {
95-
$this->days = (int) $matches[1];
105+
$this->days = (int)$matches[1];
96106
}
97107

98108
if (preg_match($this->hoursRegex, $duration, $matches)) {
99-
$this->hours = (int) $matches[1];
109+
$this->hours = (int)$matches[1];
100110
}
101111

102112
if (preg_match($this->minutesRegex, $duration, $matches)) {
103-
$this->minutes = (int) $matches[1];
113+
$this->minutes = (int)$matches[1];
104114
}
105115

106116
if (preg_match($this->secondsRegex, $duration, $matches)) {
107-
$this->seconds = (int) $matches[1];
117+
$this->seconds = (float)$matches[1];
108118
}
109119

110120
return $this;
111-
} else {
112-
return false;
113121
}
122+
123+
return false;
114124
}
115125

116126
/**
117127
* Returns the duration as an amount of seconds.
118128
*
119129
* For example, one hour and 42 minutes would be "6120"
120130
*
121-
* @param int|string $duration A string or number, representing a duration
122-
* @return int
131+
* @param int|float|string $duration A string or number, representing a duration
132+
* @param int|bool $precision Number of decimal digits to round to. If set to false, the number is not rounded.
133+
* @return int|float
123134
*/
124-
public function toSeconds($duration = null)
135+
public function toSeconds($duration = null, $precision = false)
125136
{
126-
if (! is_null($duration)) {
137+
if (!is_null($duration)) {
127138
$this->parse($duration);
128139
}
129-
130140
$this->output = ($this->days * $this->hoursPerDay * 60 * 60) + ($this->hours * 60 * 60) + ($this->minutes * 60) + $this->seconds;
131141

132-
return (int) $this->output();
142+
return $precision !== false ? round($this->output, $precision) : $this->output;
133143
}
134144

135145
/**
136-
* Returns the duration as an amount of seconds.
146+
* Returns the duration as an amount of minutes.
137147
*
138148
* For example, one hour and 42 minutes would be "102" minutes
139149
*
140-
* @param int|string $duration A string or number, representing a duration
141-
* @param boolean $roundToInteger Should the number be rounded and returned as integer
142-
* @return int
150+
* @param int|float|string $duration A string or number, representing a duration
151+
* @param int|bool $precision Number of decimal digits to round to. If set to false, the number is not rounded.
152+
* @return int|float
143153
*/
144-
public function toMinutes($duration = null, $roundToInteger = false)
154+
public function toMinutes($duration = null, $precision = false)
145155
{
146-
if (! is_null($duration)) {
156+
if (!is_null($duration)) {
147157
$this->parse($duration);
148158
}
149159

160+
// backward compatibility, true = round to integer
161+
if ($precision === true) {
162+
$precision = 0;
163+
}
164+
150165
$this->output = ($this->days * $this->hoursPerDay * 60 * 60) + ($this->hours * 60 * 60) + ($this->minutes * 60) + $this->seconds;
151166
$result = intval($this->output()) / 60;
152167

153-
return $roundToInteger ? intval(round($result, 0)) : $result;
168+
return $precision !== false ? round($result, $precision) : $result;
154169
}
155170

156171
/**
@@ -161,21 +176,21 @@ public function toMinutes($duration = null, $roundToInteger = false)
161176
* - 42 minutes would be "0:42:00"
162177
* - 28 seconds would be "0:00:28"
163178
*
164-
* @param int|string $duration A string or number, representing a duration
179+
* @param int|float|string $duration A string or number, representing a duration
165180
* @param bool $zeroFill A boolean, to force zero-fill result or not (see example)
166181
* @return string
167182
*/
168183
public function formatted($duration = null, $zeroFill = false)
169184
{
170185

171-
if (! is_null($duration)) {
186+
if (!is_null($duration)) {
172187
$this->parse($duration);
173188
}
174189

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

177-
if ($this->seconds > 0) {
178-
if ($this->seconds <= 9 && ($this->minutes > 0 || $hours > 0 || $zeroFill)) {
192+
if ($this->seconds > 0) {
193+
if ($this->seconds < 10 && ($this->minutes > 0 || $hours > 0 || $zeroFill)) {
179194
$this->output .= '0' . $this->seconds;
180195
} else {
181196
$this->output .= $this->seconds;
@@ -214,12 +229,12 @@ public function formatted($duration = null, $zeroFill = false)
214229
*
215230
* For example, one hour and 42 minutes would be "1h 42m"
216231
*
217-
* @param int|string $duration A string or number, representing a duration
232+
* @param int|float|string $duration A string or number, representing a duration
218233
* @return string
219234
*/
220235
public function humanize($duration = null)
221236
{
222-
if (! is_null($duration)) {
237+
if (!is_null($duration)) {
223238
$this->parse($duration);
224239
}
225240

@@ -251,11 +266,11 @@ public function humanize($duration = null)
251266
*/
252267
private function reset()
253268
{
254-
$this->output = '';
269+
$this->output = '';
255270
$this->seconds = 0;
256271
$this->minutes = 0;
257-
$this->hours = 0;
258-
$this->days = 0;
272+
$this->hours = 0;
273+
$this->days = 0;
259274
}
260275

261276
/**

0 commit comments

Comments
 (0)