web-dev-qa-db-fra.com

Minute ronde au quart d'heure près

Je dois arrondir les heures au quart d'heure près en PHP. Les heures sont extraites d’une base de données MySQL d’une colonne datetime et sont formatées comme suit: 2010-03-18 10:50:00.

Exemple:

  • 10:50 doit être 10:45
  • 1:12 doit être 1:00
  • 3:28 doit être 3:15
  • etc.

Je suppose que floor() est impliqué mais je ne sais pas comment s'y prendre.

Merci

45
Rob

Votre fonction complète serait quelque chose comme ça ...

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

Cet exemple obtient l'heure actuelle et l'arrondit au quartier le plus proche et imprime à la fois l'original et l'heure arrondie.

PS: Si vous souhaitez arrondir down, remplacez round() par floor().

67
Veger
$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;
11
Richard JP Le Guen

Pour arrondir le quart d'heure le plus proche, utilisez ci-dessous le code

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

01:08 deviennent 01:15

8
Mufaddal
$minutes = ($minutes - ($minutes % 15));
5
Scott Saunders

Dernièrement, j'aime aborder un problème le TDD/unit testing way. Je ne programme plus beaucoup PHP ces derniers temps, mais c'est ce que j'ai proposé. Pour être honnête, j’ai en fait jeté un œil aux exemples de code et j’ai choisi celui que j’imaginais exact. Ensuite, je voulais vérifier cela par des tests unitaires à l'aide des tests que vous avez fournis ci-dessus.

classe 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()));
        }        
    }
}

le moment d'aller en classe

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

Test en cours

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

....

Time: 0 seconds

OK (4 tests, 12 assertions)
5
Alfred

Pour mon système, je souhaitais ajouter des tâches planifiées toutes les 5 minutes sur mon serveur. Je souhaitais que la même tâche soit exécutée dans le bloc de 5e minute suivant, puis 15, 30, 60, 120, 240 minutes, 1 jour et plus. 2 jours après, c'est donc ce que cette fonction calcule

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>';
2
Sander

C'est une vieille question mais, ayant récemment moi-même mis en œuvre, je vais partager ma solution: -

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
Trent Renshaw

J'avais besoin d'un moyen de terminer ma journée en coupant tout au-delà:

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

Strtotime me donne un horodatage pour "maintenant", que gmdate convertit au format ISO (quelque chose comme "2012-06-05T04: 00: 00 + 00: 00"), puis j'utilise exploser au "T", ce qui me donne " 2012-06-05 "dans l’index zeroth de $ explodedDate, qui est ensuite passé à date_create pour obtenir un objet date. 

Je ne sais pas si tout cela est nécessaire, mais il me semble que cela demande beaucoup moins de travail que de passer et de soustraire les secondes, les minutes, les heures, etc.

1
Craig B
// 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
ram108

Voici une fonction que j'utilise actuellement:

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

J'espère que ça aide quelqu'un :)

0
Marcel Drews

Pourrait aider les autres. Pour n'importe quelle langue.

roundedMinutes = yourRoundFun(Minutes / interval) * interval.

Par exemple. L'intervalle peut être de 5 minutes, 10 minutes, 15 minutes, 30 minutes . Les minutes arrondies peuvent alors être réinitialisées à la date correspondante. 

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

J'ai écrit une fonction qui fait l'affaire pour arrondir les horodatages en secondes ou en minutes.

Je ne suis peut-être pas le moyen le plus performant, mais je pense que PHP ne se soucie pas de quelques boucles simples.

Dans votre cas, vous transmettez simplement votre date/heure MySQL comme ceci:

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

Retours: la plus proche valeur arrondie (regarde à la fois haut et bas!)

La fonction:

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

Vous remplacez simplement $ entity par 's' si vous voulez arrondir à des secondes ou plus et remplacer 15 par le nombre de secondes ou de minutes que vous souhaitez.

0
ibram

Solution simple:

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

Vous pouvez changer floor en ceil si vous voulez arrondir.

0
Rafał Schefczyk