To convert a time value into a decimal value representing the number of minutes can be useful for certain calculations. The following function takes a time as a string of hh:mm:ss and returns a decimal value in minutes.
/**
* Convert time into decimal time.
*
* @param string $time The time to convert
*
* @return integer The time as a decimal value.
*/
function time_to_decimal($time) {
$timeArr = explode(':', $time);
$decTime = ($timeArr[0]*60) + ($timeArr[1]) + ($timeArr[2]/60);
return $decTime;
}
If we take the time of 11:11:11 this gets split into 3 parts by the explode() function into hours, minutes and seconds, which then gets treated in the following way:
Minutes = (Hours x 60) + (Minutes) + (Seconds / 60)
Minutes = (11 x 60) + (11) + (11 / 60)
Minutes = (660) + (11) + (0.18333333)
Minutes = 671.18333333
The function can be used as follows:
echo time_to_decimal("11:11:11"); // prints 671.18333333
The reverse of this function takes the decimal value and returns a string in the format hh:mm:ss.
/**
* Convert decimal time into time in the format hh:mm:ss
*
* @param integer The time as a decimal value.
*
* @return string $time The converted time value.
*/
function decimal_to_time($decimal) {
$hours = floor($decimal / 60);
$minutes = floor($decimal % 60);
$seconds = $decimal - (int)$decimal;
$seconds = round($seconds * 60);
return str_pad($hours, 2, "0", STR_PAD_LEFT) . ":" . str_pad($minutes, 2, "0", STR_PAD_LEFT) . ":" . str_pad($seconds, 2, "0", STR_PAD_LEFT);
}
This function can be used as follows:
echo decimal_to_time(671.18333333); // prints 11:11:11
Note that these functions deal with amounts of time, not the time of day. Converting between time and decimal time of day requires a different set of calculations.
UPDATE: Thanks to an anonymous poster for pointing out some errors, these have now been corrected.
Comments
Hi Philip,
Your code indeed works in the manner you have described, however there are a couple of finer details that caused issues for me when using the code.
In the time_to_decimal function, line 12 should read as follows:
$decTime = ($timeArr[0]*60) + ($timeArr[1]) + ($timeArr[2]/60);
As it is written in your post, the seconds are actually representing fractions of an hour (1/3600th) as opposed to fractions of a minute (1/60th).
We have the same issue in the decimal_to_time function as well as an issue in regards to the round() function. I've corrected the decimal_to_time function as follows:
function decimal_to_time($decimal) {
$hours = floor((int)$decimal / 60);
$minutes = floor((int)$decimal % 60);
$seconds = $decimal - (int)$decimal;
$seconds = round($seconds * 60);
return str_pad($hours, 2, "0", STR_PAD_LEFT) . ":" . str_pad($minutes, 2, "0", STR_PAD_LEFT) . ":" . str_pad($seconds, 2, "0", STR_PAD_LEFT);
}
round() in lines 2 and 3 have been replaced by floor(). This is due to the behavior of round() returning 1 when given .5. An example is as follows:
Say we are converting 1:30:30 into a decimal representing minutes. Using the two functions posted we would have
echo time_to_decimal('1:30:30'); // prints 90.008333333333, seconds are still converted incorrectly
// this should display the input from the first function
echo decimal_to_time(90.008333333333); // prints 02:02:30, not correct
In the example, line 2 of the original code calculates to - round( 90 / 60 ) = round(1.5) = 2. Since we only want the numer of whole hours in the $decimal variable, we should use floor() instead. floor() will always round to the lowest whole number ( 1 in this case )
I hope this helps someone out there :)
Thank you for all the hard work you put into that comment! I really appreciate it when a user posts such detailed comments on this blog :)
I have tested your examples and updated my code accordingly.
hi tae, thanks..
i propose to change little to allow this kind of input "01:05" =1h05 or "01:05:00" or "01"=1hour
function time_to_decimal($time) {
$timeArr = explode(':', $time);
if (count($timeArr) == 3) {
$decTime = ($timeArr[0]*60) + ($timeArr[1]) + ($timeArr[2]/60);
} else if (count($timeArr) == 2) {
$decTime = ($timeArr[0]) + ($timeArr[1]/60);
} else if (count($timeArr) == 2) {
$decTime = $time;
}
return $decTime;
}
This function kept returning :60 in the seconds place! I added :
if ($seconds == 60) {
$minutes++; $seconds=0;
}
to the end of the function.
My 2 cents comment if used your function and added a format control to avoid strange behavior and surprise
function Time_To_Decimal($time) {
$decTime = 0;
if (preg_match("/^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time, $matches)) {
$decTime = ($matches[0]*60) + ($matches[1]) + ($matches[2]/60);
}
return $decTime;
}
Thanks a lot for posting
Sorry posted too quickly (fixed preg_match return array)
function Time_To_Decimal($time) {
$decTime = 0;
if (preg_match("/^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time, $matches)) {
$decTime = ($matches[1]*60) + ($matches[2]) + ($matches[3]/60);
}
return $decTime;
}
Error here
floor($decimal % 60);
and not
floor($decimal % / 60);
Quite right Gianluca, thanks for pointing that out.