I'm retrieving a datetime from a mysql field but I need to round it up to the nearest 10 minutes.
For example, If the datetime is 2013-11-06 14:00:01, I'd like to return the time as 6/11/2013 14:10.
What's the easiest way to do this?
$datetime = new DateTime($mysqldata);
echo $datetime->format('d/m/Y G:i');
Any advice appreciated.
Thanks.
1) Set number of seconds to 0 if necessary (by rounding up to the nearest minute)
$second = $datetime->format("s");
if($second > 0)
$datetime->add(new DateInterval("PT".(60-$second)."S"));
2) Get minute
$minute = $datetime->format("i");
3) Convert modulo 10
$minute = $minute % 10;
4) Count minutes to next 10-multiple minutes if necessary
if($minute != 0)
{
// Count difference
$diff = 10 - $minute;
// Add difference
$datetime->add(new DateInterval("PT".$diff."M"));
}
Edited, thanks @Ondrej Henek and @berturion
I stumbled upon this question and wondered why all the solutions are so complicated. It's simply this:
function roundToNext10Min(\DateTime $dt, $precision = 10) {
$s = $precision * 60;
$dt->setTimestamp($s * (int) ceil($dt->getTimestamp() / $s));
return $dt;
}
$dt = roundToNext10Min(new DateTime($str));
echo $dt->format('d/m/Y G:i');
Edit: I wrote this answer a long time ago, some folks discovered that milliseconds are not considered. It is worth try other answers than mine to find the perfect time rounding method.
The answer of @rand have a bug when the DateTime we want to round is already a 10-minutes multiple. It will jump to 10 minutes later while it is not wanted.
Also, always jumping to the next minute with ($datetime->add(new \DateInterval("PT".(60-$second)."S"));
is not wanted when seconds is at zero already.
This enhanced function fixes these bugs and takes a $precision parameter to cover more use cases.
function roundTime(\DateTime &$datetime, $precision = 30, $round_lower = false) {
// 1) Set number of seconds to 0 (by rounding up to the nearest minute if necessary)
$second = (int) $datetime->format("s");
if ($second > 30 && $round_lower == false) {
// 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) {
if($round_lower) {
$datetime->sub(new \DateInterval("PT".$minute."M"));
} else {
// 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"));
}
}
}
This function is now perfect for my use and probably for other folks.
Edit: Now it allows to set round upper or lower
You can use the ceil, floor and round functions to round a DateTime either up, down or to the nearest minute interval as follows:
/**
* @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
);
}
I would use timestamps:
<?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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With