it-swarm.com.de

Runden Sie die Minute auf die nächste Viertelstunde ab

Ich muss in PHP auf die nächste Viertelstunde runden. Die Zeiten werden aus einer MySQL-Datenbank aus einer datetime-Spalte abgerufen und wie 2010-03-18 10:50:00 formatiert.

Beispiel:

  • 10:50 muss 10:45 sein
  • 1:12 muss 1:00 sein
  • 3:28 muss 3:15 sein
  • usw.

Ich gehe davon aus, dass floor() involviert ist, aber nicht sicher ist, wie er vorgehen soll.

Vielen Dank

45
Rob

Ihre volle Funktion wäre so ähnlich ...

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

In diesem Beispiel wird die aktuelle Uhrzeit abgerufen und auf das nächste Viertel gerundet und sowohl die ursprüngliche als auch die gerundete Uhrzeit gedruckt.

PS: Wenn Sie es abrunden möchten , ersetzen Sie round() durch 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

Verwenden Sie den folgenden Code, um die nächste Viertelstunde abzurunden

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

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

In letzter Zeit mag ich es, ein Problem auf die TDD/Unit-Test Art anzugehen. Ich programmiere in letzter Zeit nicht viel PHP mehr, aber das ist es, worauf ich gekommen bin. Um ehrlich zu sein, habe ich mir die Codebeispiele hier angesehen und dasjenige ausgewählt, von dem ich dachte, dass es bereits richtig war. Als Nächstes wollte ich dies durch Komponententests anhand der oben angegebenen Tests überprüfen.

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

unterrichtszeit

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

Lauftest

[email protected]:~/htdocs/time$ phpunit TimeTest.php 
PHPUnit 3.3.17 by Sebastian Bergmann.

....

Time: 0 seconds

OK (4 tests, 12 assertions)
5
Alfred

Für mein System wollte ich Jobs hinzufügen, die alle 5 Minuten auf meinem Server ausgeführt werden sollen, und ich möchte, dass derselbe Job im nächsten Block von 5 Minuten ausgeführt wird, dann 15, 30, 60, 120, 240 Minuten, 1 Tag und 2 Tage danach berechnet sich diese Funktion

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

Es ist eine alte Frage, aber nachdem ich mich kürzlich selbst implementiert habe, teile ich meine Lösung mit: -

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

Ich brauchte eine Möglichkeit, mich auf den Tag abzurunden und alles, was darüber hinausgeht, abzuschneiden:

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

Die strtotime gibt mir einen Zeitstempel für "now", den gmdate in das ISO-Format konvertiert (etwas wie "2012-06-05T04: 00: 00 + 00: 00"), dann verwende ich explodieren am "T" und gebe mir " 2012-06-05 "im nullten Index von $ explodedDate, der dann an date_create übergeben wird, um ein Datumsobjekt zu erhalten. 

Ich bin mir nicht sicher, ob all dies notwendig ist, aber es scheint viel weniger Arbeit zu sein, als Sekunden, Minuten, Stunden usw. zu subtrahieren.

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

Hier ist eine Funktion, die ich gerade verwende:

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

Hoffe es hilft jemandem :)

0
Marcel Drews

Könnte anderen helfen. Für jede Sprache.

roundedMinutes = yourRoundFun(Minutes / interval) * interval.

Z.B. Das Intervall kann 5 Minuten, 10 Minuten, 15 Minuten, 30 Minuten betragen. Dann können gerundete Minuten auf das jeweilige Datum zurückgesetzt werden. 

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

Ich habe eine Funktion geschrieben, mit der Zeitstempel auf Sekunden oder Minuten gerundet werden können.

Ich bin vielleicht nicht der performanteste Weg, aber ich denke, PHP interessiert sich nicht für ein paar einfache Schleifen.

In Ihrem Fall übergeben Sie Ihre MySQL-Datetime wie folgt:

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

Rückgabe: der abgerundete Wert (schaut nach oben und unten!)

Die Funktion:

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

Sie können $ entity einfach durch 's' ersetzen, wenn Sie auf Sekunden auf- oder abrunden und 15 durch die Anzahl der Sekunden oder Minuten ersetzen möchten, auf die Sie auf oder ab gehen möchten.

0
ibram

Ich war überrascht, dass niemand die erstaunliche Carbon-Bibliothek (oft in Laravel verwendet) erwähnt hat.

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

Testfälle:

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
Ryan

Einfache Lösung:

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

Sie können floor in ceil ändern, wenn Sie aufrunden möchten.

0