Круглая минута до ближайшей четверти часа - PullRequest
45 голосов
/ 20 марта 2010

Мне нужно округлить время до ближайшего четверти часа в PHP. Время извлекается из базы данных MySQL из столбца datetime и форматируется как 2010-03-18 10:50:00.

Пример:

  • 10: 50 должно быть 10: 45
  • 1: 12 должно быть 1: 00
  • 3: 28 должно быть 3: 15
  • и т.д.

Я предполагаю, что floor() вовлечен, но не уверен, как это сделать.

Спасибо

Ответы [ 15 ]

67 голосов
/ 20 марта 2010
$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";

Этот пример получает текущее время и округляет его до ближайшего квартала и печатает как оригинальное, так и округленное время.

PS : еслиВы хотите округлить вниз заменить round() на floor().

29 голосов
/ 20 марта 2010

Ваша полная функция будет выглядеть примерно так ...

function roundToQuarterHour($timestring) {
    $minutes = date('i', strtotime($timestring));
    return $minutes - ($minutes % 15);
}
11 голосов
/ 20 марта 2010
$now = getdate();
$minutes = $now['minutes'] - $now['minutes']%15;

 //Can add this to go to the nearest 15min interval (up or down)
  $rmin  = $now['minutes']%15;
  if ($rmin > 7){
    $minutes = $now['minutes'] + (15-$rmin);
   }else{
      $minutes = $now['minutes'] - $rmin;
  }

$rounded = $now['hours'].":".$minutes;
echo $rounded;
8 голосов
/ 23 августа 2013

Для округления до ближайшего квартала используйте код

<?php
$time = strtotime("01:08");
echo $time.'<br />';
$round = 15*60;
$rounded = round($time / $round) * $round;
echo date("H:i", $rounded);
?>

01: 08 становится 01: 15

5 голосов
/ 20 марта 2010

В последнее время мне нравится решать проблему TDD / модульное тестирование . В последнее время я больше не программирую на PHP, но это то, что я придумал. Честно говоря, я на самом деле посмотрел примеры кода здесь и выбрал тот, который мне показался правильным. Затем я хотел проверить это путем модульного тестирования, используя тесты, которые вы предоставили выше.

класс 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()));
        }        
    }
}

Время урока

<?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;
    }
}

Выполнение теста

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

....

Time: 0 seconds

OK (4 tests, 12 assertions)
5 голосов
/ 20 марта 2010
$minutes = ($minutes - ($minutes % 15));
2 голосов
/ 19 октября 2016

Это старый вопрос, но, недавно внедрив себя, я поделюсь своим решением: -

public function roundToQuarterHour($datetime) {

    $datetime = ($datetime instanceof DateTime) ? $datetime : new DateTime($datetime);

    return $datetime->setTime($datetime->format('H'), ($i = $datetime->format('i')) - ($i % 15));

}

public function someQuarterHourEvent() {

    print_r($this->roundToQuarterHour(new DateTime()));
    print_r($this->roundToQuarterHour('2016-10-19 10:50:00'));
    print_r($this->roundToQuarterHour('2016-10-19 13:12:00'));
    print_r($this->roundToQuarterHour('2016-10-19 15:28:00'));

}
2 голосов
/ 29 мая 2011

Для моей системы я хотел добавить задания, которые должны запускаться на 5-й минуте на моем сервере, и я хочу, чтобы это же задание выполнялось в следующем 5-м минутном блоке, затем через 15, 30, 60, 120, 240 минут, 1 день и 2 дня после этого, вот что вычисляет эта функция

function calculateJobTimes() {
    $now = time();
    IF($now %300) {
        $lastTime = $now - ($now % 300);
    }
    ELSE {
        $lastTime = $now;
    }
    $next[] = $lastTime + 300;
    $next[] = $lastTime + 900;
    $next[] = $lastTime + 1800;
    $next[] = $lastTime + 3600;
    $next[] = $lastTime + 7200;
    $next[] = $lastTime + 14400;
    $next[] = $lastTime + 86400;
    $next[] = $lastTime + 172800;
    return $next;
}

echo "The time now is ".date("Y-m-d H:i:s")."<br />
Jobs will be scheduled to run at the following times:<br /><br />
<ul>";
foreach(calculateJobTimes() as $jTime) {
    echo "<li>".date("Y-m-d H:i:s", $jTime).'</li>';
}
echo '</ul>';
1 голос
/ 04 января 2016
// time = '16:58'
// type = auto, up, down
function round_time( $time, $round_to_minutes = 5, $type = 'auto' ) {
    $round = array( 'auto' => 'round', 'up' => 'ceil', 'down' => 'floor' );
    $round = @$round[ $type ] ? $round[ $type ] : 'round';
    $seconds = $round_to_minutes * 60;
    return date( 'H:i', $round( strtotime( $time ) / $seconds ) * $seconds );
}
1 голос
/ 08 декабря 2011

Мне нужен был способ округлить до дня и отрезать все, что за этим:

$explodedDate = explode("T", gmdate("c",strtotime("now")));
$expireNowDate =  date_create($explodedDate[0]);

strtotime дает мне метку времени для «сейчас», которое gmdate конвертирует в формат ISO (что-то вроде «2012-06-05T04: 00: 00 + 00: 00»), затем я использую разнесение на «T», давая мне «2012-06-05» в нулевом индексе $ explodedDate, который затем передается в date_create для получения объекта даты.

Не уверен, что все это необходимо, но кажется, что это намного меньше работы, чем вычитать секунды, минуты, часы и т. Д.

...