Stopwatch Script that Keeps Accurate Time

Jamie Uttariello
4 min readDec 3, 2018

Inaccurate javascript timing scripts led me to build a super-accurate stopwatch. Get the full code and documentation at GitHub.

In javascript, setTimeout() and setInterval() functions were created to run functions at set time intervals. However, they are not even close to exact time keepers and should never be used when the accuracy of the timing of events, like in a stopwatch, are vital.

What Led Me to This…

I created a stopwatch a user can use to track how long they have been studying definitions for a list of words they created. Then, I started using the stopwatch and while it was still running I went to a different browser to watch some Hulu. When I got back to my timer on my website, the timer was all wrong. I was gone for about twenty minutes and the timer was off by more than 4 minutes! I was using Chrome. I then ran an experiment on Safari and found the timer was off again, this time by 3 minutes. WTF?!?

So I went to Google and found tons of people were also frustrated by poor time tracking using setInterval() and setTimeout() in javascript. It seems the more sophisticated and ‘smart’ browsers get, the more they interfere with the original intentions of the programmer. For instance, I am not able to watch Hulu in the Chrome browser while I do things in other tabs because Chrome delays the connection for tabs not in focus. So I have to keep Safari open to watch Hulu and Chrome open to navigate the web and work.

And that explains the problem. While you are doing things in other tabs the browser’s JS engine prioritizes the tab in focus so that timing events from non-focused tabs go to the back of the queue.

After several hours of research on getting an accurate stopwatch I decided to stop researching and just build the damn thing myself. Crazy how much time programmers spend looking for other coders work when they could more easily do it from scratch themselves.

The Answer to an Accurate Stopwatch

It’s really rather simple. Get the real time when the user starts the timer and every second compare it to the current time. Display the difference. This way no matter how ‘off’ the JS timing interval gets from what the programmer actually set, the time will always be correct.

The Stopwatch HTML

<div id=”timerContainer”><div class=”timer” onclick=”startTimer()”>Start Studying!</div><div class=”startTimer reset” onclick=”startTimer()” >
<i class=”fas fa-play”></i>
</div>
<div class=”pauseTimer reset” onclick=”pauseTimer()” >
<i class=”fas fa-pause”></i>
</div>
<div class=”resetTimer reset” onclick=”resetTimer()”>Reset</div></div>

You can see what the timer looks like at my new website- Brain Bank- here. Click ‘Timer’ and it will appear, I have a simple jQuery toggle to show/hide the timerContainer. That is the only jQuery, the entire script is vanilla javascript. The i tags for play and pause are just Font Awesome fonts.

So what we have is a stopwatch with: Start — Pause — Reset

The Stopwatch Script

We will need some variables to use in our script so the first thing we do is setup variables. Then we create a function that starts the timer. Then a function to pause the timer. Then a function to reset the timer. And finally a function that keeps track of the time. In each function we add/remove some CSS classes and/or styles which make it more clear if the stopwatch is paused or active.

  1. Setup the variables we will need.
var stTimer = document.querySelector('.startTimer');
var psTimer = document.querySelector('.pauseTimer');
var timerDisplay = document.querySelector('.timer');
var startTime;
var updatedTime;
var difference;
var tInterval;
var savedTime;
var paused = 0;
var running = 0;

2. Start timer function.

function startTimer(){
if(!running){
startTime = new Date().getTime();
tInterval = setInterval(getShowTime, 1000);
paused = 0;
running = 1;
timerDisplay.style.background = "#FF0000";
timerDisplay.style.cursor = "auto";
timerDisplay.style.color = "yellow";
stTimer.classList.add('lighter');
stTimer.style.cursor = "auto";
psTimer.style.cursor = "pointer";
psTimer.classList.remove('lighter');
}
}

3. Pause timer function.

function pauseTimer(){
if (!difference){
// if timer never started, don't allow pause button to do anything
} else if (!paused) {
clearInterval(tInterval);
savedTime = difference;
paused = 1;
running = 0;
timerDisplay.style.background = "#A90000";
timerDisplay.style.color = "#690000";
timerDisplay.style.cursor = "pointer";
stTimer.style.cursor = "pointer";
psTimer.style.cursor = "auto";
stTimer.classList.remove('lighter');
psTimer.classList.add('lighter');
} else {
startTimer();
}
}

4. The reset function.

function resetTimer(){
clearInterval(tInterval);
savedTime = 0;
difference = 0;
paused = 0;
running = 0;
timerDisplay.innerHTML = 'Start Studying!';
timerDisplay.style.background = "#A90000";
timerDisplay.style.color = "#fff";
timerDisplay.style.cursor = "pointer";
stTimer.style.cursor = "pointer";
psTimer.style.cursor = "auto";
stTimer.classList.remove('lighter');
psTimer.classList.remove('lighter');
}

5. The timer function.

function getShowTime(){
updatedTime = new Date().getTime();
if (savedTime){
difference = (updatedTime - startTime) + savedTime;
} else {
difference = updatedTime - startTime;
}
// var days = Math.floor(difference / (1000 * 60 * 60 * 24));
var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((difference % (1000 * 60)) / 1000);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
timerDisplay.innerHTML = hours + ':' + minutes + ':' + seconds;
}

I have the timer set to display hours, minutes, and seconds. I have code commented out to display days and you will probably want to add milliseconds code in many cases.

Please go to https://BrainBank.cc to see the site that I created in two months, using vanilla javascript, some jQuery, Apache, PHP and MySQL. I will write future articles about Brain Bank. For now, I hope anyone who wants a stopwatch script can use this.

I will also be upgrading the stopwatch in the future so that the timer works as the user navigates Brain Bank. I plan to do this using some form of web storage or cookies.

Also, please clap as much as you can so people can find this script.

--

--