Круглая минута до ближайшей четверти часа - 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 ]

0 голосов
/ 12 апреля 2019

Я был удивлен, что никто не упомянул удивительную Библиотеку углерода (часто используется в Laravel).

/**
 * 
 * @param \Carbon\Carbon $now
 * @param int $minutesChunk
 * @return \Carbon\Carbon
 */
public static function getNearestTimeRoundedDown($now, $minutesChunk = 30) {
    $newMinute = $now->minute - ($now->minute % $minutesChunk); 
    return $now->minute($newMinute)->startOfMinute(); //https://carbon.nesbot.com/docs/
}

Контрольные примеры:

public function testGetNearestTimeRoundedDown() {
    $this->assertEquals('2018-07-06 14:00:00', TT::getNearestTimeRoundedDown(Carbon::parse('2018-07-06 14:12:59'))->format(TT::MYSQL_DATETIME_FORMAT));
    $this->assertEquals('14:00:00', TT::getNearestTimeRoundedDown(Carbon::parse('2018-07-06 14:29:25'))->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('14:30:00', TT::getNearestTimeRoundedDown(Carbon::parse('2018-07-06 14:30:01'))->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('18:00:00', TT::getNearestTimeRoundedDown(Carbon::parse('2019-07-06 18:05:00'))->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('18:45:00', TT::getNearestTimeRoundedDown(Carbon::parse('2019-07-06 18:50:59'), 15)->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('18:45:00', TT::getNearestTimeRoundedDown(Carbon::parse('2019-07-06 18:49:59'), 15)->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('10:15:00', TT::getNearestTimeRoundedDown(Carbon::parse('1999-12-30 10:16:58'), 15)->format(TT::HOUR_MIN_SEC_FORMAT));
    $this->assertEquals('10:10:00', TT::getNearestTimeRoundedDown(Carbon::parse('1999-12-30 10:16:58'), 10)->format(TT::HOUR_MIN_SEC_FORMAT));
}
0 голосов
/ 27 июля 2016

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

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

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

0 голосов
/ 03 октября 2015

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

roundedMinutes = yourRoundFun(Minutes / interval) * interval.

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

yourDateObj.setMinutes(0) 
yourDateObj.setMinutes(roundedMinutes)
0 голосов
/ 18 июня 2013

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

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

Надеюсь, это кому-нибудь поможет:)

0 голосов
/ 05 декабря 2012

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

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

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

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

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

Функция:

<?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 - на количество секунд или минут, которое хотите увеличить или уменьшить.

...