PHP では、時間を 15 分単位で切り下げる必要があります。時刻は、datetime 列から MySQL データベースから取得され、のようにフォーマットされています2010-03-18 10:50:00
。
例:
- 10:50 は 10:45 である必要があります
- 1:12 は 1:00 である必要があります
- 3:28 は 3:15 である必要があります
- 等
関与していると思いfloor()
ますが、どうすればよいかわかりません。
ありがとう
$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";
この例では、現在の時刻を取得し、最も近い四分の一に丸め、元の時刻と丸められた時刻の両方を出力します。
PS :切り捨てたい場合は に置き換えround()
てfloor()
ください。
あなたの完全な機能はこのようなものになります...
function roundToQuarterHour($timestring) {
$minutes = date('i', strtotime($timestring));
return $minutes - ($minutes % 15);
}
$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;
最近は、 TDD/単体テストの方法で問題に取り組むのが好きです。私は最近、あまり PHP をプログラミングしていませんが、これが私が思いついたものです。正直なところ、私は実際にここのコード例を見て、すでに正しいと思ったものを選びました。次に、上記で提供したテストを使用して単体テストを行い、これを確認したいと思いました。
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()));
}
}
}
<?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;
}
}
alfred@alfred-laptop:~/htdocs/time$ phpunit TimeTest.php
PHPUnit 3.3.17 by Sebastian Bergmann.
....
Time: 0 seconds
OK (4 tests, 12 assertions)
$minutes = ($minutes - ($minutes % 15));
これは古い質問ですが、最近自分自身を実装したので、解決策を共有します:-
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'));
}
私のシステムでは、サーバーで 5 分ごとに実行されるようにスケジュールされているジョブを追加したいと考えていました。同じジョブを次の 5 分のブロックで実行し、次に 15、30、60、120、240 分、1 日、 2日後なので、この関数はそれを計算します
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>';
簡単な解決策:
$oldDate = "2010-03-18 10:50:00";
$date = date("Y-m-d H:i:s", floor(strtotime($oldDate) / 15 / 60) * 15 * 60);
切り上げたい場合floor
は変更できます。ceil
日を切り捨て、それ以降のすべてを切り捨てる方法が必要でした。
$explodedDate = explode("T", gmdate("c",strtotime("now")));
$expireNowDate = date_create($explodedDate[0]);
strtotime は「今」のタイムスタンプを提供し、gmdate は ISO 形式 (「2012-06-05T04:00:00+00:00」のようなもの) に変換し、「T」で爆発を使用して、「 2012-06-05" を $explodedDate の 0 番目のインデックスに追加し、これを date_create に渡して日付オブジェクトを取得します。
そのすべてが必要かどうかはわかりませんが、秒、分、時間などを調べて差し引くよりもはるかに少ない作業のようです.
// 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 );
}
ここに私が現在使用している機能があります:
/**
* 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;
}
それが誰かを助けることを願っています:)
タイムスタンプを秒または分に丸めるトリックを行う関数を作成しました。
私は最もパフォーマンスの高い方法ではないかもしれませんが、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 を切り上げまたは切り下げたい秒数または分数に置き換えます。