0

I'm trying to figure out how to format a variable holding the number of seconds into a string that would say the time in human readable format, but round the minutes to the next 15.

Example:

$seconds = 4320; //
echo $convertAndRoundTime($seconds);
// would result in
//0 days, 1 hour and 15 minutes
// rather than 
//0 days, 1 hour and 12 minutes

I can get it to work with the exact time, such as 12 minutes using the following code (found here).

function secondsToTime($seconds) {
    $dtF = new \DateTime('@0');
    $dtT = new \DateTime("@$seconds");
    return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
}

But how can I round the minutes up to the next 15. So if it's 8 minutes, round to 15, if it's 18 minutes round to 30, etc.

UPDATE

I think I got it...

$seconds = "4320";

        $seconds = round($seconds);
        if (gmdate("i",$seconds) % 15 != 0) $seconds = round($seconds / (15 * 60)) * (15 * 60);

        $dtF = new \DateTime('@0');
        $dtT = new \DateTime("@$seconds");      
        $days = $dtF->diff($dtT)->format('%a') * 3; // calculate days as 8 hour work days       

        echo $days.' days, '.$dtF->diff($dtT)->format('%h hours, %i minutes and %s seconds');
Community
  • 1
  • 1
Phil
  • 4,029
  • 9
  • 62
  • 107

3 Answers3

1

Just divide the $seconds by 900 (15 * 60) round the result up, multiply it back by 900 and assign it to $seconds. Then format it like you need. eg:

$seconds = 4320;
$seconds = ceil($seconds / 900) * 900;
abcdn
  • 1,397
  • 14
  • 15
1

Using the method concept of @Girish and the rounding idea of @abcdn, I created the next code which makes it

class MyTimeFormatter
{
    const DAY_SECONDS    = 86400; // 60*60*24;
    const HOUR_SECONDS   = 3600; // 60*60;
    const MINUTE_SECONDS = 60; // 60;

    public static function format($timestamp, $isQuarterMinutes = true)
    {
        $days = self::getTimeInDays($timestamp);

        $timestamp -= $days * self::DAY_SECONDS;
        $hours = self::getTimeInHours($timestamp);

        $timestamp -= $hours * self::HOUR_SECONDS;
        $minutes = self::getTimeInMinutes($timestamp);

        $timestamp -= $minutes * self::MINUTE_SECONDS;
        $seconds = $timestamp;

        if ($isQuarterMinutes) {
            $minutes = self::_getMinutesInQuarter($minutes);
        }

        return sprintf(
            '%d day(s), %d hour(s), %d minute(s) and %d seconds',
            $days, $hours, $minutes, $seconds
        );
    }

    public static function getTimeInDays($timestamp)
    {
        return (int)($timestamp/self::DAY_SECONDS);
    }

    public static function getTimeInHours($timestamp)
    {
        return (int)($timestamp/self::HOUR_SECONDS);
    }

    public static function getTimeInMinutes($timestamp)
    {
        return (int)($timestamp/self::MINUTE_SECONDS);
    }

    private static function _getMinutesInQuarter($minutes)
    {
        return ceil($minutes/15) * 15;
    }
}

So if you call

$seconds = 4322;
echo MyTimeFormatter::format($seconds), "\n";
echo MyTimeFormatter::format($seconds, false), "\n";

It prints

0 day(s), 1 hour(s), 15 minute(s) and 2 seconds
0 day(s), 1 hour(s), 12 minute(s) and 2 seconds
AlphaZygma
  • 228
  • 2
  • 9
  • Quick note: you may noticed that I casted to `int` instead of using the `intval()` function, that is because of better performance and no need to change the base [see this answer](http://stackoverflow.com/questions/1912599/is-there-any-particular-difference-between-intval-and-casting-to-int-int-x) – AlphaZygma Mar 15 '17 at 17:15
0

Here is the answer:

<?php

    $seconds = 93816;

    echo getDaysTime($seconds);

    function getDaysTime($seconds) {

        $noOfDays = intval($seconds/86400);

        $remainingSeconds = $seconds%86400;

        return $noOfDays . ' day(s), ' . getHoursTime($remainingSeconds);
    }

    function getHoursTime($seconds) {

        $noOfHours = intval($seconds/3600);

        $remainingSeconds = $seconds%3600;

        return $noOfHours . ' hour(s), ' . getMinutesTime($remainingSeconds);
    }

    function getMinutesTime($seconds) {

        $noOfMinutes = intval($seconds/60);

        $remainingSeconds = $seconds%60;

        return $noOfMinutes . ' minute(s), ' . getSecondsTime($remainingSeconds);
    }

    function getSecondsTime($seconds) {
        return $seconds . ' second(s), ';
    }

?>
Girish k
  • 33
  • 5
  • Nice idea of separating functions for each part, but this still faces the issue of the rounding of the minutes to the nearest quarter, which @abcdn's solution has a good approach. Also, one thing to notice, is that perhaps your methods should only retrieve the part needed instead of the whole format, as the values returns could be reused, while with the string format may be a little less reusable. – AlphaZygma Mar 14 '17 at 21:51