Converting To And From Decimal Time In PHP

29th November 2010 - 3 minutes read time

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.

  1. /**
  2.  * Convert time into decimal time.
  3.  *
  4.  * @param string $time The time to convert
  5.  *
  6.  * @return integer The time as a decimal value.
  7.  */
  8. function time_to_decimal($time) {
  9. $timeArr = explode(':', $time);
  10. $decTime = ($timeArr[0]*60) + ($timeArr[1]) + ($timeArr[2]/60);
  11.  
  12. return $decTime;
  13. }

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:

  1. Minutes = (Hours x 60) + (Minutes) + (Seconds / 60)
  2. Minutes = (11 x 60) + (11) + (11 / 60)
  3. Minutes = (660) + (11) + (0.18333333)
  4. 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.

  1. /**
  2.  * Convert decimal time into time in the format hh:mm:ss
  3.  *
  4.  * @param integer The time as a decimal value.
  5.  *
  6.  * @return string $time The converted time value.
  7.  */
  8. function decimal_to_time($decimal) {
  9. $hours = floor($decimal / 60);
  10. $minutes = floor($decimal % 60);
  11. $seconds = $decimal - (int)$decimal;
  12. $seconds = round($seconds * 60);
  13.  
  14. 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);
  15. }

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

Permalink

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:

  1. function decimal_to_time($decimal) {
  2. $hours = floor((int)$decimal / 60);
  3. $minutes = floor((int)$decimal % 60);
  4. $seconds = $decimal - (int)$decimal;
  5. $seconds = round($seconds * 60);
  6.  
  7. 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);
  8. }

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

  1. echo time_to_decimal('1:30:30'); // prints 90.008333333333, seconds are still converted incorrectly
  2.  
  3. // this should display the input from the first function
  4. 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 :)

Anonymous (Mon, 10/03/2011 - 19:32)

Permalink

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.

Permalink

hi tae, thanks..

Anonymous (Sun, 12/18/2011 - 19:45)

Permalink
i propose to change little to allow this kind of input "01:05" =1h05 or "01:05:00" or "01"=1hour
  1. function time_to_decimal($time) {
  2. $timeArr = explode(':', $time);
  3. if (count($timeArr) == 3) {
  4. $decTime = ($timeArr[0]*60) + ($timeArr[1]) + ($timeArr[2]/60);
  5. } else if (count($timeArr) == 2) {
  6. $decTime = ($timeArr[0]) + ($timeArr[1]/60);
  7. } else if (count($timeArr) == 2) {
  8. $decTime = $time;
  9. }
  10. return $decTime;
  11. }

ffert2907 (Tue, 09/11/2012 - 12:56)

Permalink
This function kept returning :60 in the seconds place! I added :
  1. if ($seconds == 60) {
  2. $minutes++;
  3. $seconds=0;
  4. }
to the end of the function.

Matthew Galvin (Mon, 04/29/2013 - 21:19)

Permalink
My 2 cents comment if used your function and added a format control to avoid strange behavior and surprise
  1. function Time_To_Decimal($time) {
  2. $decTime = 0;
  3. if (preg_match("/^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time, $matches)) {
  4. $decTime = ($matches[0]*60) + ($matches[1]) + ($matches[2]/60);
  5. }
  6. return $decTime;
  7. }
Thanks a lot for posting

Road (Thu, 07/11/2013 - 13:53)

Permalink
Sorry posted too quickly (fixed preg_match return array)
  1. function Time_To_Decimal($time) {
  2. $decTime = 0;
  3. if (preg_match("/^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $time, $matches)) {
  4. $decTime = ($matches[1]*60) + ($matches[2]) + ($matches[3]/60);
  5. }
  6. return $decTime;
  7. }

Road (Thu, 07/11/2013 - 14:15)

Permalink
gmmktime() -> time 2 decimal

Luis (Fri, 02/13/2015 - 13:50)

Permalink

Error here

floor($decimal % 60);

and not

floor($decimal % / 60);

 

Gianluca (Mon, 05/04/2020 - 13:25)

Add new comment

The content of this field is kept private and will not be shown publicly.