LoginSignup
4
3

More than 3 years have passed since last update.

フォームに入力された開始時間、終了時間からJavaScriptを使って経過時間を算出する

Last updated at Posted at 2020-06-06

画面で開始時間、終了時間を入力されると自動的に経過時間を計算する必要があるときってありませんか!?

開発者A「<input type="time">で開始時間、終了時間は入力できるようにしたけど、経過時間の計算処理はどうすれば?(心:自分で実装するのめんどくせーからネットにいいのねえかなー?)」
私「安心してください。ありますよ。」
ってな感じで使ってもらえればいいと思い、大した内容では無いですがQiitaに初投稿することにしました。

利用想定

  • フォームに入力されたhh:mm形式の時間同士の経過時間を計算したい
  • 開始、終了時間は同一日として扱うが、開始時間 > 終了時間の場合は終了日を翌日として計算したい

動作確認環境

  • OS : windows10
  • ブラウザ:Google Chrome(81.0.4044.138)

実装

時分入力フォーム「starttime」「endtime」から時間を取り出し経過時間「elapsetime」に入力する

  • 方法1

時間のみの情報を一旦Date型にし[Date - Date = 経過ミリ秒]となる事を利用して経過ミリ秒
を算出、経過ミリ秒→経過時分(hh:mm)を算出する

method1.js
function setElapseTime() {
    const starttime= document.getElementById("starttime").value;
    const endtime= document.getElementById("endtime").value;
    document.getElementById("elapsetime").value = calElapseTime(starttime, endtime)
}

function calElapseTime(starttime, endtime) {
    //引数が時間形式(hh:mm)でない場合は計算しない
    if (!isFormatHHMM(starttime) || !isFormatHHMM(endtime)) return "";

    //経過時間算出のために一旦日付型に変換する
    //前提として同一日の時間入力同士の計算なのでDate化する際の日付は固定
    const wd = "2000/01/01";
    const startDate = new Date(`${wd} ${starttime}`);
    const endDate = new Date(`${wd} ${endtime}`);

    //開始時間 > 終了時間の場合、日を跨いでいるとして扱い、終了日に+1日する
    if (startDate > endDate) endDate.setDate(endDate.getDate() + 1);

    //終了日(終了時間) - 開始日(開始時間)を行い経過時間(ミリ秒)を算出
    const elapseMs = endDate - startDate;

    //経過時間(ミリ秒)をhh:mm形式の文字列にして返却する
    return msToTimeString(elapseMs);
}

//文字列が時間形式(hh:mm)かどうかを判定する
function isFormatHHMM(str) {
    const fmt = RegExp("^([0-1][0-9]|2[0-3]):([0-5][0-9])$");
    return fmt.test(str);
}

//ミリ秒から時分文字列(hh:mm)を作成して返す
function msToTimeString(ms) {
    //1minute = 60000ms
    //1hour = 60minutes = 3600000ms
    const hour = Math.floor(ms / 3600000);
    const minute = Math.floor((ms - 3600000 * hour) / 60000);
    const hh = ("00" + hour).slice(-2);
    const mm = ("00" + minute).slice(-2);

    return `${hh}:${mm}`;
}

いかがでしたでしょうか。
そう、思いましたね?(少なくとも私は思いました)
同一日の時間計算するのに一旦Date型に変換するのって美しくなくね?って。
そう思ったあなたお送りするのが「方法2」となります。

  • 方法2

時間情報をミリ秒に変換し[終了時間(ミリ秒) - 開始時間(ミリ秒)]で経過ミリ秒を算出した後、経過ミリ秒→経過時分(hh:mm)を算出する

method2.js
//下記のメソッド内容は省略(方法1を参照してください)
function setElapseTime() {}
function isFormatHHMM(str) {}
function msToTimeString(ms) {}

function calElapseTime(starttime, endtime) {
    //引数が時間形式(hh:mm)でない場合は計算しない
    if (!isFormatHHMM(starttime) || !isFormatHHMM(endtime)) return "";

    //各時間をミリ秒に変換する
    const startms = timeStringToMs(starttime);
    let endms = timeStringToMs(endtime);

    //開始時間 > 終了時間の場合、日を跨いでいるとして扱い+1日(1d = 86400000ms)
    if (startms > endms) endms += 86400000;

    //終了時間を行い経過時間(ミリ秒)を算出
    const elapseMs = endms - startms;

    //経過時間(ミリ秒)をhh:mm形式の文字列にして返却する
    return msToTimeString(elapseMs);
}

//時分文字列(hh:mm)からミリ秒を算出して返す
//時分文字列形式ではなかった場合は0msを返す
function timeStringToMs(hhmm) {
    //1h = 3600000ms
    //1m = 60000ms
    let ms = 0;
    const ret = hhmm.match(/^([0-1][0-9]|2[0-3]):([0-5][0-9])$/)
    if (ret != null) ms = Number(ret[1]) * 3600000 + Number(ret[2]) * 60000;
    return ms;
}

いかがでしたでしょうか。
開発者A「ラッキー!やりたいこと全部やってくれてる。丸パクリー」
と使ってもらえたら幸いです。
どちらかというと自分で再度使うべきときに備えて残したというのが正しいかもしれませんが、、

Qiitaへの投稿は初となるため、読みやすいかはちょっとまだわかりませんが、
こうすれば良いや、間違いなどあればご指摘いただければ幸いです。

4
3
5

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
4
3