1

Possible Duplicate:
Converting Seconds to HH:MM:SS

I have an integer as a number of seconds. I want to convert that integer into into hours/minutes/seconds like this:

1:45:32

If the number of seconds equates to less than one hour then it should return the string:

45:32

If the number of minutes is less than 10 it should return the string formatted like this:

3:25

And finally if the number of seconds equate to less than 1 minute, it should return the following:

0:04

What is the best way to do this in PHP?

Community
  • 1
  • 1
gordyr
  • 6,078
  • 14
  • 65
  • 123
  • Most of them piece each out into an hour calculation, minute calc, and second calc. Just use some `if()` statements to test. You should also make sure that you're being specific about what format is being used when you display it to your users, because switching it like you want to do will be confusing. – jprofitt Feb 23 '12 at 13:35
  • I began using the gmdate function gmdate("H:i:s", $seconds) which returns a full HH:MM:SS string. After this I tried several other methods I have found on various websites including stack overflow. But none of them omit the 'hour' part of the string and the leading zero's in the manner I describe. The output is being used to describe a time position in an audio file and the above formatting is the standard way of describing such lengths/positions when working with audio. – gordyr Feb 23 '12 at 13:37
  • there is a [couple more you will get when searching for your very own question title](http://stackoverflow.com/search?q=Converting+seconds+to+hours%2Fminutes%2Fseconds+in+PHP) so please use the search function next time before asking duplicates. – Gordon Feb 23 '12 at 13:51
  • not a duplicate, wanted format is (HH:)M:SS – Rufinus Feb 23 '12 at 13:51
  • @Rufinus yes, duplicate. The desired output format doesnt justify asking a new question. The two linked duplicates have everything the OP needs to make this work. And asking how to do an if/else block is not a real question anyways. – Gordon Feb 23 '12 at 14:22
  • @Gordon Perhaps to an experienced programmer the other questions would indeed provide all the necessary information required to come to a solution. For a novice like myself this is not so. More specific guidance was required. My understanding is that Stackoverflow caters for developers at all levels of expertise? Also, the very first thing I did was search on Stackoverflow. After three hours of trial and error with the found solutions, I felt a question of my own was in order. – gordyr Feb 23 '12 at 16:19
  • @gordyr tbh, i dont buy that "novice programmer" excuse anymore, but ranting about that wouldnt be constructive. So please take this advice instead: next time you ask a question put a reference to the questions you have searched and explain why they didnt solve your problem or where you hit a roadblock. Show some code you tried that didnt work. That makes it easier for us to decide whether you just were too lazy to search and want to be spoonfed a solution or whether you really couldnt figure it out. – Gordon Feb 23 '12 at 16:55
  • 2
    @Gordon Advice is always welcome. My intent is never to offend anyone, quite the contrary. The facts were as I stated them (with regards to my level of PHP knowledge) and I have to admit to being a little bemused with the apparent offsense I seem to have caused you by asking a question to which the answer had eluded me for the best part of this morning. Regardless, your advice clearly is sound, even if I disagree with the tone of it's message. And for that, I thank you. – gordyr Feb 23 '12 at 17:28

5 Answers5

8

The simpelst approch would be

if($seconds < 3600){
 $format = 'i:s';
}else{
 $format = 'G:i:s';
}

echo date($format, $seconds);

EDIT: this wouldnt fix your minutes < 10 problem. you could handle the minutes by itself. like

$time = ($seconds >= 3600) ? date('G', $seconds).':' : '';
$time .= intval(date('i',$seconds)).':'.date('s', $seconds);
Rufinus
  • 29,200
  • 6
  • 68
  • 84
  • Thanks Rufinus, this is an embarrassingly simple solution. However the php date function does not appear to support 'minutes' without the leading zero which I require. It is very close however. – gordyr Feb 23 '12 at 13:46
  • Perfect! This a great/simple approach and works excellently. Huge thanks! – gordyr Feb 23 '12 at 13:51
  • @Rufinus: Your answer [is inspiring](http://stackoverflow.com/a/9414402/367456) ;) – hakre Feb 23 '12 at 13:56
  • ALMOST! Don't forget about GMT offsets, use gmdate() instead of date(). – marcovtwout Feb 26 '13 at 09:54
1
<?php
$seconds = (1*60 + 45)*60 + 32; // 1:45:32

define("SECONDS_IN_HOUR", 3600);
define("SECONDS_IN_MINUTE", 60);

// hours
if ($seconds >= SECONDS_IN_HOUR)
{
   print floor($seconds/SECONDS_IN_HOUR) . ":";
   $seconds = $seconds % SECONDS_IN_HOUR;
}
// minutes
if ($seconds >= SECONDS_IN_MINUTE)
{
   print floor($seconds/SECONDS_IN_MINUTE) . ":";
   $seconds = $seconds % SECONDS_IN_MINUTE;
}

// seconds
print $seconds;
?>
Basti
  • 3,998
  • 1
  • 18
  • 21
  • 1
    i love your defines... for the case sometime in the next 1000 years a hour has more than 3600 seconds :-) – Rufinus Feb 23 '12 at 13:53
  • it's about code readability. `$seconds % SECONDS_IN_MINUTE` is much more descriptive than `$seconds % 3600` or `$seconds % (60*60)`. a common style flaw is to have arbitrary numbers in your code, nobody but you knows what they mean. so use descriptive constant names instead. – Basti Feb 23 '12 at 13:57
1

I think Rufinus is pretty close:

foreach(array(60 => ' 0:s', 3600 => 'i:s', 'G:i:s') as $val => $format)
{
    if ($seconds < $val) break;
}
echo ltrim(ltrim(gmdate($format, $seconds), '0'), ' ');

This variant uses a configuration stored inside an array which associates a format string based on a time value in seconds (as key). The last element is the default format that will fall through.

Edit: Unfortunately there is no formatting code in date that allows to specify minutes w/o a leading there. Therefore the date string needs to be re-formatted to remove leading 0's occasionally. It's done with ltrim here.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • unfortunately "I" (uppercase i) is summertime 0/1 :) – Rufinus Feb 23 '12 at 13:57
  • Oh that's a pitty :(, there is [no 0-59 minute formatting code](http://php.net/date). – hakre Feb 23 '12 at 13:59
  • i fallen for it to when i tried it :) – Rufinus Feb 23 '12 at 14:01
  • @Rufinus: I combined this now with an idea I had earlier. Works now ;) – hakre Feb 23 '12 at 14:05
  • try it with 3604 :) he wants H:M:SS (and you seem to have a bug, as for 3604 it shows 2:00:04) – Rufinus Feb 23 '12 at 14:11
  • That depends on the default timezone, mine is UTC, good point. Fixed that by using `gmdate` which is independent to configuration. I wonder how this could work for multiple days. – hakre Feb 23 '12 at 14:17
  • i guess you have to calc it the hard way. devide by 3600 to get the hours, the rest by 60 for minutes, the rest by 60 for seconds. – Rufinus Feb 23 '12 at 14:21
  • Yeah I did that for some function (x days/mins/secs ago / just now) already, but liked the niceness of your first example. But obvisouly, that's only useful below one day (or additionally up to ~360 days but the ltrim doesn't work well then any longer). – hakre Feb 23 '12 at 14:24
0
function formatHMS($time) {
    $s = $time % 60;
    $time= floor($time/60);

    $m = $time % 60;
    $time= floor($time/60);

    $h = floor($time);

    $str = $s;

    if ($m>0)
        $str = "$m:$str";
    if ($h>0)
        $str = "$h:$str";

    return $str;

}
alexg
  • 3,015
  • 3
  • 23
  • 36
-3

Consider using explode() & implode() and then apply your logic of less-than & greater-than!

linuxeasy
  • 6,269
  • 7
  • 33
  • 40