時間の範囲を検査する方法

佐野

佐野 2013年8月2日

先日、突如難題が入りました。

PHPにて23時から翌日8時ぐらいまで、
システムの一部を一時停止させたいという問題でした。
しかも毎日使えるように、入力される情報は、
開始時刻と終了時刻の「時」と「分」の4つの数値のみです。

本来は厳密には自分の担当ではなく、相談された事なのですが、
プログラムの流れとしてはほぼ同じようなものなので、
デバッグ機能を備えたGoogleAppsScriptのエディタを利用し、
JavaScriptで試してみました。

しかし、これが意外にも難しく、
その日の範囲ならば、単純にUNIX時間(1970年元日からの秒数)で計ればいいのですが、
日をまたいでいると、そうはいきません。
開始時刻と終了時刻に日付も含まれていれば簡単なのですが、
毎日使うため、そうもいきません。

何度か相談しつつも、なんとかこの問題を解決出来たのですが、
自分自身では解決には至らず、先を越されていました。

結論としては、開始時刻の「時」が終了時刻の「時」よりも大きい場合は、
翌日であると判断して処理を分け、開始時刻と終了時刻のUNIX時間を生成し範囲を作り、
現在のUNIX時間と比較するという結論になりました。

しかしその翌日に、自分のJavaScript版を完成させてみました。


//現時刻が時間の範囲に入っているかを見る関数。
// 引数1:開始時  引数2:開始分  引数3:終了時  引数4:終了分
//それぞれ数値で入力。
function timeRangeCheck(startTimeHours,startTimeMinutes,endTimeHours,endTimeMinutes){
  
  //現在時刻が指定の範囲に入っていればtrueになる。
  var timeRangeIn = false;
  
  var date = new Date();
  var yy = date.getYear();
  var mm = date.getMonth() + 1;//getMonth()での1月は0から始まるため、1加算。
  var dd = date.getDate();
  
  var nowUnixTime = Date.parse(date);
  var startUnixTime = Date.parse(yy+"/"+mm+"/"+dd+" "+startTimeHours+":"+startTimeMinutes+":0");
  var endUnixTime = Date.parse(yy+"/"+mm+"/"+dd+" "+endTimeHours+":"+endTimeMinutes+":0");
  
  //開始時刻が終了時刻を上回っていたら翌日と判断し、終了時刻に1日分のUNIX時間(GAS基準)を追加。
  if((endTimeHours * 60) + endTimeMinutes < (startTimeHours * 60) + startTimeMinutes){
    endUnixTime += 86400000;
  }
  
  //現時刻が開始時刻以上、終了時刻以下の範囲になるとtrueにする。
  if(nowUnixTime >= startUnixTime && nowUnixTime <= endUnixTime){
    timeRangeIn = true;
  }
  
  return timeRangeIn;
}

GoogleApps用の関数はないため、
たぶん、通常のウェブページ用としても使えると思います。
ただ、途中で1日分の秒数を入力している箇所では、
GoogleAppsScript上で1日分のUNIX時間を計算したものなので、
もしかしたら、用途によってはケタ数に誤差が生じるかもしれません。

自分が独自に考えた方法では、開始時刻の「時」が終了時刻の「時」を
越えていた場合には翌日と判断するのは共通していますが、
ここで終了時刻のUNIX時間に、1日分の秒数を加算するという方法を取りました。
これで比較用のUNIX時間が作成できたので、
後は現時国のUNIX時間が、この範囲に入っているかを計算するだけです。

ただ、さらに問題を見つけました。
このままでは分単位で終了時刻が翌日になっていた場合、
たとえば開始時刻が「12:40」で、終了時刻が翌日の「12:30」であるとしたら、
終了時刻が翌日であると判断されていませんでした。

そこで考えたのが、開始時刻と終了時刻を、「時」「分」まるごと
分単位に修正して比較しようという考えです。

修正前・・・

//開始時刻の「時」が終了時刻の「時」を上回っていたら翌日と判断し、終了時刻に1日分のUNIX時間(GAS基準)を追加。
if(endTimeHours < startTimeHours){
  endUnixTime += 86400000;
}

 
 
修正後・・・

//開始時刻が終了時刻を上回っていたら翌日と判断し、終了時刻に1日分のUNIX時間(GAS基準)を追加。
if((endTimeHours * 60) + endTimeMinutes < (startTimeHours * 60) + startTimeMinutes){
  endUnixTime += 86400000;
}

これで、分単位で翌日になるよう修正しました。

今後、このような計測の仕方を行う事がありそうなので、
こちらも上記のコードは関数として保存し、今後使えるようにしました。
以上のコードは、勝手に使用していただいても結構です。