tags:

views:

694

answers:

5

I need to round times down to the nearest quarter hour in PHP. The times are being pulled from a MySQL database from a datetime column and formatted like 2010-03-18 10:50:00.

Example: 10:50 needs to be 10:45 1:12 needs to be 1:00 3:28 needs to be 3:15 etc.

I'm assuming floor() is involved but not sure how to go about it.

Thanks

+1  A: 
$minutes = ($minutes - ($minutes % 15));
Scott Saunders
So 1:19 becomes (19%15)*15 = 4*15 = 60!?
LeguRi
Thanks Richard. My head is somewhere else.
Scott Saunders
not %!!! you need floor!!!:)
Syom
@Syom try executing the code, it works.
Andy
+5  A: 
$now = getdate();
$minutes = floor($now['minutes']/15)*15;

$rounded = $now['hours'].":".$minutes;
echo $rounded;

or

$now = getdate();
$minutes = $now['minutes'] - $now['minutes']%15;

$rounded = $now['hours'].":".$minutes;
echo $rounded;
LeguRi
A: 
$seconds = time();
$rounded_seconds = round($seconds / (15 * 60)) * (15 * 60);

echo "Original: " . date('H:i', $seconds) . "\n";
echo "Rounded: " . date('H:i', $rounded_seconds) . "\n";

This example gets the current time and rounds it to the nearest quarter and prints both the original and the rounded time.

PS: If you want to round it down replace round() with floor().

Veger
A: 

Your full function would be something like this...

function roundToQuarterHour($timestring) {
    $minutes = date('i', strtotime($timestring));
    return $minutes - ($minutes % 15);
}
Wickethewok
removed the function and went this route:$start_minutes = date('i', strtotime($row['start']));$minutes_floor = $start_minutes - ($start_minutes % 15);
Rob
+1  A: 

Lately I like tackling a problem the TDD/unit testing way. I am not programming much PHP anymore lately, but this is what I came up with. To be honest I actually looked at the code examples here, and picked the one I thought was already correct. Next I wanted to verify this by unit testing using the tests you provided above.

class TimeTest

require_once 'PHPUnit/Framework.php';
require_once 'Time.php';

class TimeTest extends PHPUnit_Framework_TestCase 
{
    protected $time;

    protected function setUp() {
        $this->time = new Time(10, 50);
    }

    public function testConstructingTime() {
        $this->assertEquals("10:50", $this->time->getTime());
        $this->assertEquals("10", $this->time->getHours());
        $this->assertEquals("50", $this->time->getMinutes());        
    }

    public function testCreatingTimeFromString() {
        $myTime = Time::create("10:50");
        $this->assertEquals("10", $myTime->getHours());
        $this->assertEquals("50", $myTime->getMinutes());
    }

    public function testComparingTimes() {
        $timeEquals     = new Time(10, 50);
        $this->assertTrue($this->time->equals($timeEquals));
        $timeNotEquals  = new Time(10, 44);
        $this->assertFalse($this->time->equals($timeNotEquals));
    }


    public function testRoundingTimes()
    {
        // Round test time.
        $roundedTime = $this->time->round();
        $this->assertEquals("10", $roundedTime->getHours());
        $this->assertEquals("45", $roundedTime->getMinutes());

        // Test some more times.
        $timesToTest = array(
            array(new Time(1,00), new Time(1,12)),
            array(new Time(3,15), new Time(3,28)),
            array(new Time(1,00), new Time(1,12)),
        );

        foreach($timesToTest as $timeToTest) {
            $this->assertTrue($timeToTest[0]->equals($timeToTest[0]->round()));
        }        
    }
}

class Time

<?php

class Time
{
    private $hours;
    private $minutes;

    public static function create($timestr) {
        $hours      = date('g', strtotime($timestr));
        $minutes    = date('i', strtotime($timestr));
        return new Time($hours, $minutes);
    }

    public function __construct($hours, $minutes) {
        $this->hours    = $hours;
        $this->minutes  = $minutes;
    }

    public function equals(Time $time) {
        return  $this->hours == $time->getHours() &&
                 $this->minutes == $time->getMinutes();
    }

    public function round() {
        $roundedMinutes = $this->minutes - ($this->minutes % 15);
        return new Time($this->hours, $roundedMinutes);
    }

    public function getTime() {
        return $this->hours . ":" . $this->minutes;
    }

    public function getHours() {
        return $this->hours;
    }

    public function getMinutes() {
        return $this->minutes;
    }
}

Running Test

alfred@alfred-laptop:~/htdocs/time$ phpunit TimeTest.php 
PHPUnit 3.3.17 by Sebastian Bergmann.

....

Time: 0 seconds

OK (4 tests, 12 assertions)
Alfred