入力された時間と分( 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
*/