Accurate and Easy Stopwatch in JavaScript

This article shows you how to create an accurate Stopwatch in Javascript. In another article, we have already created a simple stopwatch(See here). But there is a problem you might observe the result of Stopwatch is not accurate.

The reason for the problem is we depend on setTimeout() method alone. The setTimeout() calls the callback method at the specified milliseconds only but the code execution time of the callback depends on the scheduler that may cause a delay in execution time.

To overcome the above problem, in this article we are going to use the Date.now() along with setTimeout() to make it more accurate.

We will also see how to create it using setInterval() method. There are little differences between setTimeout() and setInterval().

Accurate stopwatch using javascript
Stopwatch using Javascript

Let’s start creating a more accurate stopwatch…

Creating Stopwatch using setTimeout() method

You just need to follow the below steps:

  1. Define HTML
  2. Define CSS
  3. Define Javascrpt logic

1. Define HTML

<!DOCTYPE html>
<html>
  <head>
      <title>JavaScript StopWatch</title>
  </head>
  <body>
    <div id="stopwatch-container">
      <p id="stopwatch">00:00:00:00</p>
      <div id="buttons-container">
        <button onclick="main()" id="main-btn" class="btn">Start</button>
        <button onclick="reset()" id="reset-btn" class="btn">Reset</button>
      </div>
    </div>
  </body>
</html>

Explanation:

  • Defined an HTML <p> tag with id="stopwatch" to display the time in 00:00:00:00 format.
  • Defined two buttons with id="main-btn" and id="reset-btn" to operate stopwatch application.
  • Creating a div area as a container with id="stopwatch-container" to contain stopwatch.

2. Define CSS

#stopwatch-container {
  display: flex;
  justify-content: center;
  flex-direction: column;
  margin: 100px auto 0;
  width: fit-content;
  padding: 10px 20px;
  box-shadow: 1px 0px 4px 2px #9c9a9a;
  border-radius: 5px;
}

#stopwatch {
  margin: 0 auto;
  text-align: center;
  font-size: 60px;
}

#buttons-container {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}

#buttons-container button {
  outline: none;
  cursor: pointer;
  color: #fff;
  background-color:#000;
  border: none;
  border-radius: 5px;
  font-size: 20px;
  margin: 0 10px;
  padding: 3px 8px;
}

#buttons-container button:active {
  opacity: 0.7;
}

3. Define Javascript logic

//globle variables
var stopwatch = document.getElementById('stopwatch');
var mainButton = document.getElementById('main-btn');
var startTime=0;
var elapsedTime=0;
var timeoutId=null;

//method to operate start and stop function
function main(){
  if (mainButton.innerHTML === 'Start') {
  startTime = Date.now();
    startStopwatch();
    mainButton.innerHTML = 'Stop';
  } else {
    elapsedTime += Date.now() - startTime;
    clearTimeout(timeoutId);
    mainButton.innerHTML = 'Start';
  }
}

//method to reset the stopwatch
function reset() {
  elapsedTime = 0;
  startTime = Date.now();
  clearTimeout(timeoutId);
  mainButton.innerHTML = 'Start';
  displayTime(0, 0, 0, 0);  
}

//method to start the stopwatch
function startStopwatch() {
 
  //run setTimeout() and save id
  timeoutId = setTimeout(function(){
    //calculate elapsed time
    const time = Date.now() - startTime + elapsedTime;
    
    //calculate different time measurements based on elapsed time
    const milliseconds = parseInt((time%1000)/10)
    const seconds = parseInt((time/1000)%60)
    const minutes = parseInt((time/(1000*60))%60)
    const hour = parseInt((time/(1000*60*60))%24);
    
	//display time
    displayTime(hour, minutes, seconds, milliseconds);
    
    //calling same method again recursively 
    startStopwatch();
  }, 100);
}

//method to display time in '00:00:00:00' format
function displayTime(hour, minutes, seconds, milliseconds) {
	hour = hour < 10 ? '0'+hour : hour ;
    minutes = minutes < 10 ? '0'+minutes : minutes ;
    seconds = seconds < 10 ? '0'+seconds : seconds ;
    milliseconds = milliseconds < 10 ? '0'+milliseconds : milliseconds ;
	stopwatch.innerHTML = hour+':'+minutes+':'+seconds+':'+milliseconds;
}

Explanation:

  • We have Defined some global variables here as stopwatch, mainButton, startTime, elapsedTime, and timeoutId.
  • stopwatch hold the reference of <p> tag element to display the time.
  • mainButton is used to hold the reference of main button to update the button text(start and stop).
  • startTime and elapsedTime are used to hold the start time and elapsed time respectively.
  • timeoutId hold the id returnd by setTimeout() and it is used to clear or stop the timer.
  • We have defined four method as main(), startStopwatch(), displayTime(), and reset().
  • The main() method is used to operate the start and stop functionality of the stopwatch.
  • The startStopwatch() method is used to calculate the time in hour, minute, seceond, and milliseconds. We call this method recursively to continue calculating the same.
  • Here we used setTimeout() method which executes only once, that is why we called startStopwatch() recursively to repeat the process.
  • The displayTime() method is used to display the time in 00:00:00:00 format.
  • The reset() method is used to reset the stopwatch. Here we clearTimeout() method to clear the timer by passing the timeoutId.

Complete Stopwatch Application

Below is the complete example(putting all HTML, CSS, and Javascript code in a single file) of a stopwatch application using the setTimeout() method and Date.now() method.

<!DOCTYPE html>
<html>
  <head>
    <title>JavaScript StopWatch</title>
    <style> 
	#stopwatch-container {
	  display: flex;
	  justify-content: center;
	  flex-direction: column;
	  margin: 100px auto 0;
	  width: fit-content;
	  padding: 10px 20px;
	  box-shadow: 1px 0px 4px 2px #9c9a9a;
	  border-radius: 5px;
	}

	#stopwatch {
	  margin: 0 auto;
	  text-align: center;
	  font-size: 60px;
	}

	#buttons-container {
	  display: flex;
	  justify-content: center;
	  flex-wrap: wrap;
	}

	#buttons-container button {
	  outline: none;
	  cursor: pointer;
	  color: #fff;
	  background-color:#000;
	  border: none;
	  border-radius: 5px;
	  font-size: 20px;
	  margin: 0 10px;
	  padding: 3px 8px;
	}

	#buttons-container button:active {
	  opacity: 0.7;
	}
  </style>
  </head>
  <body>
    <div id="stopwatch-container">
      <p id="stopwatch">00:00:00:00</p>
      <div id="buttons-container">
        <button onclick="main()" id="main-btn" class="btn">Start</button>
        <button onclick="reset()" id="reset-btn" class="btn">Reset</button>
      </div>
    </div>
    <script>
	//globle variables
	var stopwatch = document.getElementById('stopwatch');
	var mainButton = document.getElementById('main-btn');
	var startTime=0;
	var elapsedTime=0;
	var timeoutId=null;

	//method to operate start and stop function
	function main(){
	  if (mainButton.innerHTML.trim() === 'Start') {
	  startTime = Date.now();
		startStopwatch();
		mainButton.innerHTML = 'Stop';
	  } else {
		elapsedTime += Date.now() - startTime;
		clearTimeout(timeoutId);
		mainButton.innerHTML = 'Start';
	  }
	}

	//method to reset the stopwatch
	function reset() {
	  elapsedTime = 0;
	  startTime = Date.now();
	  clearTimeout(timeoutId);
	  mainButton.innerHTML = 'Start';
	  displayTime(0, 0, 0, 0);  
	}

	//method to start the stopwatch
	function startStopwatch() {
	 
	  //run setTimeout() and save id
	  timeoutId = setTimeout(function(){
		//calculate elapsed time
		const time = Date.now() - startTime + elapsedTime;
		
		//calculate different time measurements based on elapsed time
		const milliseconds = parseInt((time%1000)/10)
		const seconds = parseInt((time/1000)%60)
		const minutes = parseInt((time/(1000*60))%60)
		const hour = parseInt((time/(1000*60*60))%24);
		
		//display time
		displayTime(hour, minutes, seconds, milliseconds);
		
		//calling same method again recursivaly
		startStopwatch();
	  }, 100);
	}

	//method to display time in '00:00:00:00' format
	function displayTime(hour, minutes, seconds, milliseconds) {
		hour = hour < 10 ? '0'+hour : hour ;
		minutes = minutes < 10 ? '0'+minutes : minutes ;
		seconds = seconds < 10 ? '0'+seconds : seconds ;
		milliseconds = milliseconds < 10 ? '0'+milliseconds : milliseconds ;
		stopwatch.innerHTML = hour+':'+minutes+':'+seconds+':'+milliseconds;
	}
    </script>
  </body>
</html>

Preview and Live Demo

00:00:00:00

Creating Stopwatch using setInterval() method

The setInterval() method in JavaScript is used to repeat a specified function at every given time interval. The setInterval() method continues calling the function until clearInterval() is called, or the window is closed.

Here we use the same HTML and CSS code from the above example only we need to modify the javascript logic.

    //globle variables
	var stopwatch = document.getElementById('stopwatch');
	var mainButton = document.getElementById('main-btn');
	var startTime=0;
	var elapsedTime=0;
	var intervalId=null;

	//method to operate start and stop function
	function main(){
	  if (mainButton.innerHTML === 'Start') {
	  startTime = Date.now();
		startStopwatch();
		mainButton.innerHTML = 'Stop';
	  } else {
		elapsedTime += Date.now() - startTime;
		clearInterval(intervalId);
		mainButton.innerHTML = 'Start';
	  }
	}

	//method to reset the stopwatch
	function reset() {
	  elapsedTime = 0;
	  startTime = Date.now();
	  clearInterval(intervalId);
	  mainButton.innerHTML = 'Start';
	  displayTime(0, 0, 0, 0);  
	}

	//method to start the stopwatch
	function startStopwatch() {
	 
	  //run setInterval() and save id
	  intervalId = setInterval(function(){
		//calculate elapsed time
		const time = Date.now() - startTime + elapsedTime;
		
		//calculate different time measurements based on elapsed time
		const milliseconds = parseInt((time%1000)/10)
		const seconds = parseInt((time/1000)%60)
		const minutes = parseInt((time/(1000*60))%60)
		const hour = parseInt((time/(1000*60*60))%24);
		
		//display time
		displayTime(hour, minutes, seconds, milliseconds);		
		
	  }, 100);
	}

	//method to display time in '00:00:00:00' format
	function displayTime(hour, minutes, seconds, milliseconds) {
		hour = hour < 10 ? '0'+hour : hour ;
		minutes = minutes < 10 ? '0'+minutes : minutes ;
		seconds = seconds < 10 ? '0'+seconds : seconds ;
		milliseconds = milliseconds < 10 ? '0'+milliseconds : milliseconds ;
		stopwatch.innerHTML = hour+':'+minutes+':'+seconds+':'+milliseconds;
	}

NOTE: Here you may notice we are not calling the startStopwatch() method recursively because we used setInterval() method and it calls the callback method every time after the specified interval by default.

Conclusion

Here you have seen creating a Stopwatch application using the setTimeout() as well as the setInterval(). You have also seen we use Date.now() method to make it more accurate.

Hope you like it. If you have any queries related to this article, write them down in the comment section below.

You may also like:

Share with friends

Leave a Comment

Your email address will not be published. Required fields are marked *