Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

JavaScript ストップウォッチの経過時間の表記の考え方について

解決したいこと

私はストップウォッチのタイマーを写経しています。
以下の問題がわかりません。
プログラミング的な思考方法を教えて下さい。

発生している問題・エラー

const currentTime = new Date(Date.now() - startTime + stopTime);

の意味がわかりません。(エラーではありません。)

該当するソースコード

main.js

const time = document.getElementById('time');
const startButton = document.getElementById('start');
const stopButton = document.getElementById('stop');
const resetButton = document.getElementById('reset');

// 開始時間
let startTime;
// 停止時間
let stopTime = 0;
// タイムアウトID
let timeoutID;

// 時間を表示する関数
function displayTime() {
  const currentTime = new Date(Date.now() - startTime + stopTime); //今回の問題の部分
  const h = String(currentTime.getHours()-9).padStart(2, '0');
  const m = String(currentTime.getMinutes()).padStart(2, '0');
  const s = String(currentTime.getSeconds()).padStart(2, '0');
  const ms = String(currentTime.getMilliseconds()).padStart(3, '0');

  time.textContent = `${h}:${m}:${s}.${ms}`;
  timeoutID = setTimeout(displayTime, 10);
}

// スタートボタンがクリックされたら時間を進める
startButton.addEventListener('click', () => {
  startButton.disabled = true;
  stopButton.disabled = false;
  resetButton.disabled = true;
  startTime = Date.now();
  displayTime();
});

// ストップボタンがクリックされたら時間を止める
stopButton.addEventListener('click', function() {
  startButton.disabled = false;
  stopButton.disabled = true;
  resetButton.disabled = false;
  clearTimeout(timeoutID);
  stopTime += (Date.now() - startTime);
});

// リセットボタンがクリックされたら時間を0に戻す
resetButton.addEventListener('click', function() {
  startButton.disabled = false;
  stopButton.disabled = true;
  resetButton.disabled = true;
  time.textContent = '00:00:00.000';
  stopTime = 0;
});

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>ストップウォッチ</title>
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
        <h1>stopwatch</h1>
        <div id="container">
            <div id="time">00:00:00</div>
            <div id="buttons">
                <input id="start" type="button" value="start">
                <input id="stop" type="button" value="stop">
                <input id="reset" type="button" value="reset">
            </div>
        </div>
    <script src="main.js"></script>
    </body>
</html>

style.css

html, body{
    font-family:"Roboto mono";
    font-size:16px;
    background-color: #1e90ff;
}

h1{
    color:#ffffff;
    text-align:center;
    font-size:2rem;
    margin:3rem;
}

#container{
    background-color:#ffffff;
    width:540px;
    border-radius:1rem;
    margin: .5rem;
    padding:1.5rem;
}

#time{
    color:#1e90ff;
    font-size:3rem;
    text-align:center;
    padding:1rem;
    border-radius:1rem;
    box-shadow:0 0 20px rgba(0, 139, 253, 0.25);
}

#buttons{
    font-size:3rem;
    text-align:center;
}

#start, #stop, #reset{
    font-size:1.5rem;
    border-radius: .3rem;
    box-shadow:0 0 20px rgba(77, 78, 79, 0.25)
}

自分で試したこと

const currentTime = new Date(Date.now() - startTime + stopTime);

から

const currentTime = new Date(Date.now());

にしました。

参考サイト

0

4Answer

currentTime変数に代入されているnew Date()の引数には、現在時刻から開始時間を引き、さらに停止時間を足した値が指定されています。これで現在のカウント時間を取得することができます。

参考にされている記事ではこのように説明されていますね。
それぞれ現在時刻はDate.now()、開始時間はstartTime、停止時間はstopTime、結果として得られる現在のカウント時間がcurrentTimeということになります。

例えばconsole.log(Date.now(), startTime, stopTime);のようにそれぞれの値を観測してみましょう。

最初にstartを押した時点では現在時刻と開始時間は同じであり、停止時間も0なので、カウントは0からスタートします。

// 現在時刻、開始時間、終了時間
1712220977402 1712220977402 0

時間が経過するに従って現在時刻の方が開始時間より大きくなりその差が広がっていくので、カウントが増えていきます。

// 現在時刻、開始時間、終了時間
1712220977413 1712220977402 0
1712220977424 1712220977402 0
1712220977434 1712220977402 0
1712220977445 1712220977402 0

stopを押して再度startを押すと、開始時間が更新され現在時刻と同じになります。そのままではまた0からカウントがスタートしてしまうので。stopが押された時に経過していた時間を加算します。

// 現在時刻、開始時間、終了時間
1712221115701 1712221115701 224

こういった説明でいかがでしょうか?

0Like

そのわからないは

Date.now() が何を表していて

Date.now() メソッドは、UTC (協定世界時) での 1970 年 1 月 1 日 0 時 0 分 0 秒 から現在までの経過時間をミリ秒単位で返します。

new Date(value) がどの様な引数なのか

世界協定時 (UTC) 1970 年 1 月 1 日午前 0 時 0 分 0 秒 (ECMAScript 元期、 UNIX 元期と等価) からのミリ秒数を整数値で表し、うるう秒は無視します。大部分の UNIX Timestamp 関数は秒単位の精度しかないことに注意してください。

がわからないって話ですか?

それとも Date.now() - startTime + stopTime が何を計算 している がわからないのでしょうか?

計算内容は上記のメソッドの定義から求められるとは思いますが。

0Like

このコードが理解できないのは、変数の名前付けが悪いせいというのもありますね。
コードは次のような意味を持っています。

「トータル経過時間を日付型オブジェクトで表現した値」 = new Date( Date.now() - 「ストップウォッチ開始ボタンを押した瞬間のタイムスタンプ」 + 「ストップウォッチでこれまでに計測した時間のトータルミリ秒」 );

このように、3つの変数はそれぞれ別の種類の値を格納する変数です。
しかし3つの変数すべてがxxxxxTimeという変数名になっているせいで、これらに同じ種類の値が格納されているかのような勘違いを誘発させます。

0Like

まず最初に日時(2024年4月4日21時30分など)と時間(15分間など)がまったく違う値だということを意識しないといけません。
そしてこの二種類の値で加算や減算をした結果が何になるのかを。

以下の表は複雑そうに見えますが、「4月4日8:00に30分を足すと4月4日8:30」「4月4日8:00から4月4日7:00を引くと1時間」のようなごく日常的に使われる日時や時間の計算を整理しただけのものです。

結果
日時+日時 変な値
日時-日時 時間
日時+時間 日時
日時-時間 日時
時間+日時 日時
時間-日時 変な値
時間+時間 時間
時間-時間 時間

Date.now()が日時であることは理解できると思います。
次はstartTimeやstopTimeが日時なのか時間なのかを代入式の部分を見て考えてください。
それがわかると他のコメントで書かれていることが納得できるのではないでしょうか。

0Like

Your answer might help someone💌