2013-11-06 4 views
8

Я извлекаю datetime из поля mysql, но мне нужно округлить его до до ближайших 10 минут.PHP DateTime округляется до ближайших 10 минут

Например, если дата-время - 2013-11-06 14:00:01, я хотел бы вернуть время как 6/11/2013 14:10.

Что это самый простой способ сделать это?

$datetime = new DateTime($mysqldata); 

echo $datetime->format('d/m/Y G:i'); 

Любые советы, оцененные.

Спасибо.

+0

проверить это http://php.net/manual/en/function.date.php –

ответ

15

1) Установить число секунд до 0, если это необходимо (путем округления до ближайшей минуты)

$second = $datetime->format("s"); 
if($second > 0) 
    $datetime->add(new DateInterval("PT".(60-$second)."S")); 

2) Получить минуту

$minute = $datetime->format("i"); 

3) Преобразование по модулю 10

$minute = $minute % 10; 

4) Подсчитайте минуты до следующих 10-кратных минут, если необходимо

if($minute != 0) 
{ 
    // Count difference 
    $diff = 10 - $minute; 
    // Add difference 
    $datetime->add(new DateInterval("PT".$diff."M")); 
} 

Edited, благодаря @Ondrej Henek и @berturion

+0

Это не точная, когда время уже делится на 10 минут или на 0 секунд. Он добавляет 10 минут или 60 секунд соответственно, поэтому он не является надежным. Ниже приведена улучшенная версия. –

+1

Спасибо, теперь нужно исправить. – rand

0

вам нужно использовать strtotime() функцию для преобразования даты в отметку времени, то добавлять или удалять минут, например

<?php 
$datenow = date("Y-m-d H:i:s", time()); 
$maketime = strtotime($datenow); 

$minutes  = 10; 

$after_10min = date("Y-m-d H:i:s", ($maketime+(60*$minutes))); 
$before_10min = date("Y-m-d H:i:s", ($maketime-(60*$minutes))); 

echo "Date now : $datenow <br />"; 
echo "Date After $minutes min : $after_10min <br />"; 
echo "Date Before $minutes min : $before_10min <br />"; 
?> 
1
public function roundupMinutesFromDatetime(\Datetime $date, $minuteOff = 10) 
{ 
    $string = sprintf(
     "%d minutes %d seconds", 
     $date->format("i") % $minuteOff, 
     $date->format("s") 
    ); 

    return $date->sub(\DateInterval::createFromDateString($string)); 
} 

И испытание:

public function datetimeProvider() 
{ 
    return array(
     array('2015-01-01 15:16:17', '2015-01-01 15:10:00'), 
     array('2015-01-01 09:59:39', '2015-01-01 09:50:00'), 
    ); 
} 

/** 
* @dataProvider datetimeProvider 
*/ 
public function testRoundupToMinutesFromDatetime($dateStr, $dateStrAssert) 
{ 
    $format = 'Y-m-d H:i:s'; 

    $date = \DateTime::createFromFormat($format, $dateStr); 
    $date = $this->repo->roundupMinutesFromDatetime($date); 
    $this->assertEquals($dateStrAssert, $date->format('Y-m-d H:i:s')); 
} 

весело.

+0

Это округление до более раннего времени – user3698243

11

Ответ @rand имеет ошибку, когда DateTime, которую мы хотим округлить, уже является 10-минутным кратным. Он будет прыгать через 10 минут, пока он не нужен.

Кроме того, всегда прыгать на следующую минуту с ($datetime->add(new \DateInterval("PT".(60-$second)."S")); не требуется, если секунды уже на нуле.

Эта улучшенная функция исправляет эти ошибки и принимает параметр $ precision, чтобы охватить больше случаев использования.

function roundTime(\DateTime $datetime, $precision = 30) { 
    // 1) Set number of seconds to 0 (by rounding up to the nearest minute if necessary) 
    $second = (int) $datetime->format("s"); 
    if ($second > 30) { 
     // Jumps to the next minute 
     $datetime->add(new \DateInterval("PT".(60-$second)."S")); 
    } elseif ($second > 0) { 
     // Back to 0 seconds on current minute 
     $datetime->sub(new \DateInterval("PT".$second."S")); 
    } 
    // 2) Get minute 
    $minute = (int) $datetime->format("i"); 
    // 3) Convert modulo $precision 
    $minute = $minute % $precision; 
    if ($minute > 0) { 
     // 4) Count minutes to next $precision-multiple minutes 
     $diff = $precision - $minute; 
     // 5) Add the difference to the original date time 
     $datetime->add(new \DateInterval("PT".$diff."M")); 
    } 
} 

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

+0

Пробовал, и @berturion прав. Это должен быть принятый ответ. – Pere

+0

Пробовал тоже, это прекрасно! Спасибо. – Naeh

1

Я хотел бы использовать временные метки:

<?php 

function roundTime(\DateTime $datetime, $precision = 10) { 

    $ts = $datetime->getTimestamp(); 
    $s = ($precision * 60); 
    $remainder = $ts % $s; 

    if ($remainder > 0) { 
     $datetime->setTimestamp($ts + $s - $remainder); 
    } 

    return $datetime; 
} 

echo roundTime(\DateTime::createFromFormat('Y-m-d H:i:s', '2016-03-04 09:00:00')) 
    ->format('Y-m-d H:i:s'); 
// prints: 2016-03-04 09:00:00 


echo roundTime(\DateTime::createFromFormat('Y-m-d H:i:s', '2016-03-04 09:00:01')) 
    ->format('Y-m-d H:i:s'); 
// prints: 2016-03-04 09:10:00 
2

Вы можете использовать CEIL, пол и круглые функции округлить DateTime либо вверх, вниз или в ближайший минутный интервал следующим образом:

/** 
* @param \DateTime $dateTime 
* @param int $minuteInterval 
* @return \DateTime 
*/ 
public function roundUpToMinuteInterval(\DateTime $dateTime, $minuteInterval = 10) 
{ 
    return $dateTime->setTime(
     $dateTime->format('H'), 
     ceil($dateTime->format('i')/$minuteInterval) * $minuteInterval, 
     0 
    ); 
} 

/** 
* @param \DateTime $dateTime 
* @param int $minuteInterval 
* @return \DateTime 
*/ 
public function roundDownToMinuteInterval(\DateTime $dateTime, $minuteInterval = 10) 
{ 
    return $dateTime->setTime(
     $dateTime->format('H'), 
     floor($dateTime->format('i')/$minuteInterval) * $minuteInterval, 
     0 
    ); 
} 

/** 
* @param \DateTime $dateTime 
* @param int $minuteInterval 
* @return \DateTime 
*/ 
public function roundToNearestMinuteInterval(\DateTime $dateTime, $minuteInterval = 10) 
{ 
    return $dateTime->setTime(
     $dateTime->format('H'), 
     round($dateTime->format('i')/$minuteInterval) * $minuteInterval, 
     0 
    ); 
} 
1

Я наткнулся на этот вопрос и задался вопросом, почему все решения настолько сложны.Это просто:

function roundToNext10Min(\DateTime $dt, $precision = 10) { 
    $s = $precision * 60; 
    $dt->setTimestamp($s * ceil($dt->getTimestamp()/$s)); 
    return $dt; 
} 

$dt = roundToNext10Min(new DateTime($str)); 
echo $dt->format('d/m/Y G:i'); 
+0

Это лучший ответ! – Acyra

0

Легкий код

<?php 
    function next10Minutes() { 
     $time = time() + 600; 

     $nextMinutes = floor(date("i", $time)/10) * 10; 

     if ($nextMinutes < 10) { 
      $nextMinutes = "00"; 
     } 

     return strtotime(date("d-m-Y H:{$nextMinutes}:00", $time)); 
    } 
Смежные вопросы