I've got a page that shows a countdown timer. To continue the countdown if the page is reloaded, it stores the time that the timer was started when the page was first loaded (or if the timer runs down) in a cookie named "timer". On page load, it checks for this cookie and calculates how much time is remaining in the countdown: it subtracts "timer" from the current time to get the elapsed time, then subtracts this from the total time for the countdown (1 day). The remaining time is passed to the function that starts the timer, startTimer
, as duration
.
startTimer
records when it was called in start
. To calculate the current value for the countdown, the timer function (timer
) subtracts start
from the current time to get the time elapsed for the current page load, then subtracts this from the remaining time duration
.
The following snippet shows the countdown, but cannot truly show the page load behavior, due to security restrictions (cookies are blocked):
function startTimer(duration, display) {
var start = Date.now(),
diff,
hours,
minutes,
seconds;
function timer() {
// get the number of seconds that have elapsed since
// startTimer() was called
diff = duration - (((Date.now() - start) / 1000) | 0);
// does the same job as parseInt truncates the float
hours = ((diff / 3600) % 24) | 0;
minutes = ((diff / 60) % 60) | 0;
seconds = (diff % 60) | 0;
hours = hours < 10 ? "0" + hours : hours;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = hours + ":" + minutes + ":" + seconds;
if (diff <= 0) {
start = Date.now() + 1000;
}
}
timer();
setInterval(timer, 1000);
}
/* document.cookie isn't accessible in SO snippets,
* so a try/catch block and use of cookieStore
* was added to the cookie functions (not present
* in production code)
*/
window.cookieStore ||= {};
function getCookie(name) {
try {
var match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
return match ? match[1] : null;
} catch (err) {
return window.cookieStore[name];
}
}
function setCookie(name, value) {
try {
document.cookie = name + "=" + value + "; max-age=" + 24 * 60 * 60;
} catch (err) {
window.cookieStore[name] = value;
return;
}
}
if (! getCookie('timer')) {
setCookie('timer', Date.now());
} else if ((-1 * (getCookie('timer') - Date.now()) / 3600 / 24) >= (60 * 24)) {
setCookie('timer', Date.now());
}
window.onload = function () {
var timing = 60 * (60 * 24 -(Date.now() - getCookie('timer')) / 3600 / 24),
display = document.querySelector('#time');
startTimer(timing, display);
};
<div id="time"></div>
When I load the page, the countdown display 23:59:59, this is fine.
I wait a couple of seconds, then I press refresh. The countdown value is higher than expected by a few seconds or minutes. For example, I refreshed the page at 23:59:32, it showed 23:59:37.
I compared the countdown rate to a watch and it's not going too fast or too slow that I could tell.
So I presume, the value set or get from the cookie for the difference duration is wrong calculated, but I don't get it.