skip to Main Content

I am using the following function to round the time to closest 15 minutes.

function roundTime($time){

    $seconds = $time;
    $rounded_seconds = round($seconds / (15 * 60)) * (15 * 60);

    return date('H:i', $rounded_seconds) . "n";
    
}

What I actually need it to be able to round UP or round DOWN to closest 15 minutes, OR 30 minutes of my choice. Separate functions can be used for each.

After searching for rounding up/down, I am aware of the functions floor and ceil but I can’t understand how to use them with time?

For example, if I have the time of 14:05, I would like to be able to round it up to closes 15 min, for example 14:15, and to round up to closes 30 min, 14:30 I want to be able to decide weather to round up or down.

Instead of rounding to closest 15 min, I want to be able to round UP or round DOWN to closes 15 min, if that makes sense.

The code is used for clocking system. The employee needs to have full 15 minutes in order for it to count as overtime. For example, if they clock out at 14:26, they get paid until 14:15.

2

Answers


  1. You would have to add two parameters to your function: The wanted interval, 15 or 30 minutes, and whether you want to round down or up. Something like this:

    function roundTime(int $seconds, int $intervalInMinutes, bool $roundDown)
    {
        $functionName    = $roundDown ? 'floor' : 'ceil';
        $intervalSeconds = $intervalInMinutes * 60;    
        $roundedSeconds  = $functionName($seconds / $intervalSeconds) * $intervalSeconds;
        return date('H:i', $roundedSeconds) . "n";
    }
    

    Live demo: https://3v4l.org/g75tA

    It is very similar to the function you had apart from some optimizations.

    Login or Signup to reply.
  2. If you want something fully flexible where you can choose the rounding interval and the direction, you can pass these options in as arguments to the function, perhaps like this:

    function roundTime($timestamp, $interval, $direction){
    
        $rounded_seconds = 0;
    
        switch ($direction) {
            case "u": //round up
                $rounded_seconds = ceil($timestamp / ($interval * 60)) * ($interval * 60);
                break;
            case "d": //round down
                $rounded_seconds = floor($timestamp / ($interval * 60)) * ($interval * 60);
                break;
            default:
                echo "default";
        }
    
        return date('H:i', $rounded_seconds) . "n";
        
    }
    
    $testTimes = [
        "2023-05-30 14:05",
        "2023-05-30 14:23",
        "2023-05-30 14:35",
        "2023-05-30 14:40",
        "2023-05-30 14:55"
    ];
    
    foreach ($testTimes as $time)
    {
        echo "base time: ".$time.PHP_EOL;
        echo "round up to 15 mins: ".roundTime(strtotime($time), 15, "u");
        echo "round up to 30 mins: ".roundTime(strtotime($time), 30, "u");
        echo "round down to 15 mins: ".roundTime(strtotime($time), 15, "d");
        echo "round down to 30 mins: ".roundTime(strtotime($time), 30, "d"); 
        echo PHP_EOL;
    }
    

    This test data will output:

    base time: 2023-05-30 14:05
    round up to 15 mins: 14:15
    round up to 30 mins: 14:30
    round down to 15 mins: 14:00
    round down to 30 mins: 14:00
    
    base time: 2023-05-30 14:23
    round up to 15 mins: 14:30
    round up to 30 mins: 14:30
    round down to 15 mins: 14:15
    round down to 30 mins: 14:00
    
    base time: 2023-05-30 14:35
    round up to 15 mins: 14:45
    round up to 30 mins: 15:00
    round down to 15 mins: 14:30
    round down to 30 mins: 14:30
    
    base time: 2023-05-30 14:40
    round up to 15 mins: 14:45
    round up to 30 mins: 15:00
    round down to 15 mins: 14:30
    round down to 30 mins: 14:30
    
    base time: 2023-05-30 14:55
    round up to 15 mins: 15:00
    round up to 30 mins: 15:00
    round down to 15 mins: 14:45
    round down to 30 mins: 14:30
    

    Live demo: https://3v4l.org/oqOTE

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search