LoginSignup
5
9

More than 5 years have passed since last update.

[PHP] 指定した単位で、時間を切り上げ・切捨てる

Last updated at Posted at 2016-12-02

入力された時間と分( hh:mm のような書式 )を5分単位にするという案件

そもそも、入力単位を5分単位にしておけばいいはずです。
が、いろいろ事情があって、5分単位で入力されるとは限らない状況のため、作成しました。

遠方のチームと連携したプロジェクトをやっていたりすると、ルール付けというのは大変です。

関数化した経緯

  • 切り捨て、切り上げの関数はあるけれど、指定した単位で行うのはちょっと工夫がいる
  • DateTime 関数では「分」のフォーマットは2桁のみ。1桁がない。
  • 切り上げ/切捨てするには、「分」を2桁フォーマットから整数に変換する必要がある。
  • 切り上げた「分」が60分だったら、1時間プラスしてあと、「分」を0に戻す
  • フォーマットはしょっちゅう変わりそうなので、Datetime オブジェクトを返し、後は好きにしてもらう

はじめに思ったよりも、処理が長く複雑になったので、関数にしました。
特に、日付フォーマットで「分」に1桁がないのは大きかったです。

切り上げ、切捨ての切替えを引数で切り替えようかと思いましたが、
1機能1関数で考えて分けています。

こういう場合、くっつけるのがいいのか、それともひとつの関数の機能はひとつと割り切るべきなのか。
個人的には後者と考えています。が、ご意見があればコメントお願いします。

/**
 * 時間(hhmm)を指定した分単位で切り上げる
 * 
 * @param $time 時間と分の文字列(1130, 11:30など)
 * @param $per 切り上げる単位(分) 5分なら5
 * @return false or 切り上げられた DateTime オブジェクト(->fomat で自由にフォーマットして使用する)
 */
function ceilPerTime($time, $per=5){

    // 値がない時、単位が0の時は false を返して終了する
    if( !isset($time) || !is_numeric($per) || ($per == 0 )) {
        return false;
    }else{
        $deteObj = new DateTime($time);
        // 指定された単位で切り上げる
        // フォーマット文字 i だと、 例えば1分が 2桁の 01 となる(1桁は無い)ので、整数に変換してから切り上げる
        $ceil_num = ceil(sprintf('%d', $deteObj->format('i'))/$per) *$per;

        // 切り上げた「分」が60になったら「時間」を1つ繰り上げる
        // 60分 -> 00分に直す
        $hour = $deteObj->format('H');

        if( $ceil_num == 60 ) {
            $hour = $deteObj->modify('+1 hour')->format('H');
            $ceil_num = '00';
        }
        $have = $hour.sprintf( '%02d', $ceil_num );

        return new DateTime($have);
    }
}

/**
 * 時間(hhmm)を指定した分単位で切り捨てる
 * 
 * @param $time 時間と分の文字列(1130, 11:30など)
 * @param $per 切り捨てる単位(分) 5分なら5
 * @return false or 切り捨てられた DateTime オブジェクト(->fomat で自由にフォーマットして使用する)
 */
function floorPerTime($time, $per=5){

    // 値がない時、単位が0の時は false を返して終了する
    if( !isset($time) || !is_numeric($per) || ($per == 0 )) {
        return false;
    }else{
        $deteObj = new DateTime($time);

        // 指定された単位で切り捨てる
        // フォーマット文字 i だと、 例えば1分が 2桁の 01 となる(1桁は無い)ので、整数に変換してから切り捨てる
        $ceil_num = floor(sprintf('%d', $deteObj->format('i'))/$per) *$per;

        $hour = $deteObj->format('H');

        $have = $hour.sprintf( '%02d', $ceil_num );

        return new DateTime($have);
    }
}


$time = '13:51';

echo '元の時刻: ' . $time."<br>";

$ceilRes = ceilPerTime($time, 5);
echo '切り上げ: ' . $ceilRes->format('H:i')."<br>";

$florrRes = floorPerTime($time, 5);
echo '切り捨て: ' . $florrRes->format('H:i')."<br>";

/* 結果

元の時刻: 1351
切り上げ: 1355
切り捨て: 1350
*/
5
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9