Круглый минут до ближайшего квартала

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

Пример:

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

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

благодаря

Ваша полная функция будет что-то вроде этого …

 function roundToQuarterHour($timestring) { $minutes = date('i', strtotime($timestring)); return $minutes - ($minutes % 15); } 
 $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() .

 $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; 

Чтобы округлить ближайший четверть часа, используйте код ниже

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

 $minutes = ($minutes - ($minutes % 15)); 

В последнее время мне нравится решать проблему методом TDD / unit testing . В последнее время я больше не программирую много 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())); } } } по 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())); } } } по 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 минут на моем сервере, и я хочу, чтобы одна и та же работа выполнялась в следующем блоке 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("Ymd H:i:s")."<br /> Jobs will be scheduled to run at the following times:<br /><br /> <ul>"; foreach(calculateJobTimes() as $jTime) { echo "<li>".date("Ymd H:i:s", $jTime).'</li>'; } echo '</ul>'; 

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

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

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

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

 // 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 ); } 

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

 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')); } 

Я написал функцию, которая выполняет трюк, чтобы округлить отметки времени до секунд или минут.

Я, возможно, не самый эффективный способ, но я думаю, что PHP не заботится о нескольких простых циклах.

В вашем случае вы просто передаете дату и время MySQL следующим образом:

 <?php echo date('d/m/Y - H:i:s', roundTime(strtotime($MysqlDateTime), 'i', 15)); ?> 

Возвращает: округленное значение closests (выглядит как вверх, так и вниз!)

Функция:

 <?php function roundTime($time, $entity = 'i', $value = 15){ // prevent big loops if(strpos('is', $entity) === false){ return $time; } // up down counters $loopsUp = $loopsDown = 0; // loop up $loop = $time; while(date($entity, $loop) % $value != 0){ $loopsUp++; $loop++; } $return = $loop; // loop down $loop = $time; while(date($entity, $loop) % $value != 0){ $loopsDown++; $loop--; if($loopsDown > $loopsUp){ $loop = $return; break; } } $return = $loop; // round seconds down if($entity == 'i' && date('s', $return) != 0){ while(intval(date('s', $return)) != 0){ $return--; } } return $return; } ?> 

Вы просто заменяете $ entity на 's', если хотите округлить до или до секунды и заменить 15 на количество секунд или минут, на которые вы хотите перевернуть вверх или вниз.

Вот функция, которую я сейчас использую:

 /** * Rounds a timestamp * * @param int $input current timestamp * @param int $round_to_minutes rounds to this minute * @param string $type auto, ceil, floor * @return int rounded timestamp */ static function roundToClosestMinute($input = 0, $round_to_minutes = 5, $type = 'auto') { $now = !$input ? time() : (int)$input; $seconds = $round_to_minutes * 60; $floored = $seconds * floor($now / $seconds); $ceiled = $seconds * ceil($now / $seconds); switch ($type) { default: $rounded = ($now - $floored < $ceiled - $now) ? $floored : $ceiled; break; case 'ceil': $rounded = $ceiled; break; case 'floor': $rounded = $floored; break; } return $rounded ? $rounded : $input; } 

Надеюсь, это кому-то поможет 🙂

Могут помочь другим. Для любого языка.

 roundedMinutes = yourRoundFun(Minutes / interval) * interval. 

Например, интервал может составлять 5 минут, 10 минут, 15 минут, 30 минут. Затем округленные минуты могут быть сброшены на соответствующую дату.

 yourDateObj.setMinutes(0) yourDateObj.setMinutes(roundedMinutes) 

Простое решение:

 $oldDate = "2010-03-18 10:50:00"; $date = date("Ymd H:i:s", floor(strtotime($oldDate) / 15 / 60) * 15 * 60); 

Вы можете сменить floor на ceil если хотите округлить.