4

For example if I have:

$seconds = 3744000; // i want to output: 43 days, 8 hours, 0 minutes

Do I have to create a function to convert this? Or does PHP already have something built in to do this like date()?

supercoolville
  • 8,636
  • 20
  • 52
  • 69
  • 1
    You could easily do this with the [`date()` function](http://php.net/manual/en/function.date.php) – Lix May 19 '12 at 19:48
  • I tried date() but it wouldnt calculate over 31 days. Was I doing something wrong? – supercoolville May 19 '12 at 19:50
  • 1
    @supercoolville you didn't do anything wrong, `date()` won't do what you want. – Aaron W. May 19 '12 at 19:57
  • `date()` is for formatting timestamps since the Unix Epoch, not for formatting date strings in the way that (for example) `uptime` does. There is a DateInterval in PHP 5.3, but according to the comments it doesn't calculate what you need. You'll need to make your own simple function that uses modulo arithmetic and remainders to work out how many whole days, then how many seconds left, then how many whole hours that is, then how many minutes left, etc. – IBBoard May 19 '12 at 19:57
  • 1
    Possible duplicate of [Convert seconds into days, hours, minutes and seconds](http://stackoverflow.com/questions/8273804/convert-seconds-into-days-hours-minutes-and-seconds) – j08691 Sep 20 '16 at 13:51

4 Answers4

22
function secondsToWords($seconds)
{
    $ret = "";

    /*** get the days ***/
    $days = intval(intval($seconds) / (3600*24));
    if($days> 0)
    {
        $ret .= "$days days ";
    }

    /*** get the hours ***/
    $hours = (intval($seconds) / 3600) % 24;
    if($hours > 0)
    {
        $ret .= "$hours hours ";
    }

    /*** get the minutes ***/
    $minutes = (intval($seconds) / 60) % 60;
    if($minutes > 0)
    {
        $ret .= "$minutes minutes ";
    }

    /*** get the seconds ***/
    $seconds = intval($seconds) % 60;
    if ($seconds > 0) {
        $ret .= "$seconds seconds";
    }

    return $ret;
}

print secondsToWords(3744000);
Ian Gregory
  • 5,770
  • 1
  • 29
  • 42
2

This is very simple and easy to find days , hours, minute and second in core php :

$dbDate = strtotime("".$yourdbtime."");
$endDate = time();
$diff = $endDate - $dbDate;
$days = floor($diff/86400);
$hours = floor(($diff-$days*86400)/(60 * 60));
$min = floor(($diff-($days*86400+$hours*3600))/60);
$second = $diff - ($days*86400+$hours*3600+$min*60);

 if($days > 0) echo $days." Days ago";
 elseif($hours > 0) echo $hours." Hours ago";
 elseif($min > 0) echo $min." Minutes ago";
 else echo "Just now";
SaNdY
  • 518
  • 4
  • 14
2

An easy way to accomplish this nowadays is using DateTimeImmutable, DateInterval and PHP 5.5.0 or higher:

$seconds = 3744000;

$interval = new DateInterval("PT{$seconds}S");
$now = new DateTimeImmutable('now', new DateTimeZone('utc'));

$difference = $now->diff($now->add($interval))->format('%a days, %h hours, %i minutes');

The result will be:

43 days, 8 hours, 0 minutes

The code adds the seconds to a date and calculates the difference to it. Like this, the seconds are transformed into the specified days, hours and minutes.


Warning 1: Working without UTC - Clock changes

You may not specify the DateTimeZone in the constructor of the DateTimeImmutable object to UTC.

$now = new DateTimeImmutable();

There are regions in this world, where the clock changes on specific days of the year. Most countries in the EU change between a summer- and winter-time for example.

If your date interval overlaps the day on that a clock change occurs and your server is set to the related region for that clock change, the result might change as well. This is best shown with the following example:

$twentyFourHours = new DateInterval('PT24H');
$twentyFiveHours = new DateInterval('PT25H');

//Pacific time changed from summer- to winter-time on that day
$summerToWinter = new DateTimeImmutable('2018-11-04');

If you add 24 hours to the $summerToWinter date, you will get the following result:

$extra24Hours = $summerToWinter->add($twentyFourHours);
echo $summerToWinter->format('y-m-d H:i');
echo $extra24Hours->format('y-m-d H:i');
echo $summerToWinter->diff($extra24Hours)->format('%a days, %h hours, %i minutes');

18-11-04 00:00

18-11-04 23:00

0 days, 24 hours, 0 minutes

As you can see, between 00:00 and 23:00 on that day lay 24 hours, which is technically correct. Because of the clock change the timelap between 02:00 and 03:00 occured twice on that day.

Adding 25 hours will result in this:

$extra25Hours = $summerToWinter->add($twentyFiveHours);
echo $summerToWinter->format('y-m-d H:i');
echo $extra25Hours->format('y-m-d H:i');
echo $summerToWinter->diff($extra25Hours)->format('%a days, %h hours, %i minutes');

18-11-04 00:00

18-11-05 00:00

1 days, 0 hours, 0 minutes

As we can see, 1 day elapsed, that has had 25 hours. If this is applied for the 3744000 seconds from the original question, the result would show:

43 days, 7 hours, 0 minutes

The information, that an elapsed day has had 25 hours, is not shown though.

Also, I was not able to recreate the same effect for a day that changes the clock from winter to summer time, that should only elapse 23 hours.


Warning 2: Working with the raw DateInterval object

Using this code without DateTimeImmutable will cause the wrong output:

$seconds = 3744000;
$interval = new DateInterval("PT{$seconds}S");
$difference = $interval->format('%a days, %h hours, %i minutes, %s seconds');

Now, only the seconds are set in the DateInterval object. $difference would be:

(unknown) days, 0 hours, 0 minutes, 3744000 seconds

Philipp Maurer
  • 2,480
  • 6
  • 18
  • 25
1

I like Ian Gregory's answer the most and upvoted it but thought i'd just simplify it a little bit :

function secondsToWords($seconds)
{
    $days = intval(intval($seconds) / (3600*24));
    $hours = (intval($seconds) / 3600) % 24;
    $minutes = (intval($seconds) / 60) % 60;
    $seconds = intval($seconds) % 60;

    $days = $days ? $days . ' days' : '';
    $hours = $hours ? $hours . ' hours' : '';
    $minutes = $minutes ? $minutes . ' minutes' : '';
    $seconds = $seconds ? $seconds . ' seconds' : '';

    return $days . $hours . $minutes . $seconds;
}
Frank
  • 243
  • 1
  • 2
  • 14