@@ -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