I have a timer and a time. The time format is like the currentTime variable in my code. I want to get the currentTime time and add +1 to it every second keeping the same time format. Also I would like to subtract the currentTime + 1 - the total hours but keeping it real time with setInterval. Hope I am clear about my questions. Thanks.
HTML
<button id="start">START</button>
<button id="pause">PAUSE</button>
<div id="output"></div>
Javscript
const startTimeButton = document.querySelector("#start")
const pauseTimeButton = document.querySelector("#pause")
const output = document.querySelector("#output");
let currentTime = "12: 42: 17";
let totalHours = 30;
let seconds = 0;
let interval = null;
const timer = () => {
seconds++;
// Get hours
let hours = Math.floor(seconds / 3600);
// Get minutes
let minutes = Math.floor((seconds - hours * 3600) / 60);
// Get seconds
let secs = Math.floor(seconds % 60);
if (hours < 10) {
hours = `0${hours}`;
}
if (minutes < 10) {
minutes = `0${minutes}`;
}
if (secs < 10) {
secs = `0${secs}`;
}
return `${hours}:${minutes}:${secs}`;
};
startTimeButton.addEventListener("click", () => {
pauseTimeButton.style.display = "flex";
startTimeButton.style.display = "none";
console.log("START TIME CLICKED");
if (interval) {
return;
}
interval = setInterval(timer, 1000);
});
pauseTimeButton.addEventListener("click", () => {
pauseTimeButton.style.display = "none";
startTimeButton.style.display = "flex";
console.log("PAUSE TIME CLICKED");
clearInterval(interval);
interval = null;
});
// Here is an example of what I would like to achive
// currentTime + 1 (each second)
// output.innerHTML = (parseInt(currentTime) + 1) - totalHours;
I have a stopwatch for a small tool here, I received most of the code from a previous question and I was going about trying to implement it, I began breaking it down and trying to understand it.
So far I think I understand most of it (Still some bits I am researching); however I was trying to adapt the code to my tool.
My requirements:
A start/stop button (a single button) - the value will change depending on if the timer is running or not.
A reset button - this will simply reset the timer to 00:00:00 and if the tool is running it will also stop it.
So far, the reset button is not configured, this is fine. The start and stop button works; however say I stopped the timer, and then started it again without resetting it, the timer just begins at 00:00:00 again, it will not continue from where it was paused.
It would be greatly appreciated if anyone would be able to explain how I could do this? I have tried the following:
Storing 'differenceInMillis for each loop of updateTimer() in a global variable, then subtracting the value from startTime = Date.now() each time the timer is restarted (This was suggested by a user in a previous question), I could not get this to work.
The code I have so far -
HTML (buttons and clock):
const outputElement = document.getElementById("outputt");
var startTime = 0;
var running = 0;
var splitcounter = 0;
function startstop() {
if (running == 0) {
running = 1;
startTime = Date.now();
startstopbutton.value = 'Stop';
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
updateTimer();
} else {
running = 0;
// logTime();
startstopbutton.value = 'Start';
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
function updateTimer() {
if (running == 1) {
let differenceInMillis = Date.now() - startTime;
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
requestAnimationFrame(updateTimer);
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst" id='btnRst' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
UPDATE new version - does not work however - session storage does not work at SO so will have to test elsewhere
const outputElement = document.getElementById("outputt");
var startTime = 0;
var running = 0;
var splitcounter = 0;
function startstop() {
if (running == 0) {
running = 1;
startTime = new Date(sessionStorage.getItem("time"))
if (isNaN(startTime)) startTime = Date.now();
startstopbutton.value = 'Stop';
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
updateTimer();
} else {
running = 0;
logTime();
startstopbutton.value = 'Start';
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
function updateTimer() {
if (running == 1) {
let differenceInMillis = Date.now() - startTime;
sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
requestAnimationFrame(updateTimer);
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
If you MUST use a date object, you will need to change
startTime = Date.now();
to
startTime = new Date(sessionStorage.getItem("time"))
if (isNaN(startTime)) startTime = Date.now();
and save the time
let differenceInMillis = Date.now() - startTime;
sessionStorage.setItem("time",differenceInMillis)
If not, use a counter instead of a date object
Also when you use a toggle as boolean, make it and use it as a boolean (good practice - not mandatory for this issue)
const outputElement = document.getElementById("outputt");
let counter = 0,
running = false,
splitcounter = 0,
lastTime = 0;
function startstop() {
running = !running;
startstopbutton.value = running ? 'Stop' : 'Start';
document.getElementById("outputt").style.backgroundColor = running ? "#2DB37B" : "#B3321B";
if (running) updateTimer(0)
}
function updateTimer(currentTime) {
if (running) requestAnimationFrame(updateTimer)
if (currentTime >= (lastTime + 1000)) {
counter++;
lastTime = currentTime;
let {
hours,
minutes,
seconds
} = calculateTime(counter * 1000);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst" id='btnRst' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
A single cookie timer (meaning value) is an idea without a hitch, I want it to pause after 1 hour and start doing what it means after clicking on a motion.
Google didn't help. https://jsfiddle.net/m6vqyeu8/
Please share your version or help wrote your own.
<!doctype html>
<html>
<head>
<title>timer</title>
<meta charset=utf-8>
</head>
<script>
let initialValue = 0.50000096;
let multiplier = 0.00000001;
let getCookie = (c_name) => {
let i, x, y, ARRcookies = document.cookie.split(";");
for (i = 0; i < ARRcookies.length; i++) {
x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g, "");
if (x == c_name) {
return unescape(y);
}
}
}
let setCookie = (c_name, value, exdays) => {
let exdate = new Date();
exdate.setDate(exdate.getDate() + exdays);
let c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
document.cookie = c_name + "=" + c_value;
}
let lastUpdated = getCookie('lastUpdated') * 1;
if (!lastUpdated) {
lastUpdated = Date.now();
setCookie('lastUpdated', lastUpdated, 9999);
}
let diff = (Date.now() - lastUpdated) / 1000;
let cu = (diff * multiplier) + initialValue;
let doCu = () => {
document.getElementById('cu').innerHTML = cu.toFixed(8);
cu = cu + multiplier;
}
document.write("<div id='cu' style='text-align: center; font-size: 40pt'></div>\n");
setInterval(doCu, 1000);
doCu();
</script>
<body>
</body>
</html>
In order to pause and resume the counter you should save the return value of the setInterval funciton and clear it or create a new one for pause and resume. Here is the example:
let interval = setInterval(doCu, 1000)
doCu()
function stop() {
clearInterval(interval)
}
function resume() {
interval = setInterval(doCu, 1000)
}
Add that to the end of your script and add 2 buttons like the following in order to be able to test it.
<button onclick="stop()">
Pause
</button>
<button onclick="resume()">
Resume
</button>
To stop the timer after one hour you can add the following code
// Stop the timer after one hour has passed.
// setTimeout calls function stop (that is used to pause the timer aswell) after 1 hour
// 1000 milis is a second. Times 60 is a minute. Times 60 is an hour
setTimeout(stop, 1000 * 60 * 60)
For the timer to automatically stop after an hour from the moment you click resume change the resume function like this:
function resume() {
interval = setInterval(doCu, 1000)
// When you resume the timer, add a timeout so it will stop in an hour.
setTimeout(stop, 1000 * 60 * 60)
}
I have updated the fiddle so you can see how it is completed.
Updated JSFiddle Link
EDIT:
Made timer stop after an hour
Renamed pause function to stop so it is more clear what it does.
Added ability to stop timer after an hour after resume
I would like to know how you could create a simple count up timer using date.now.
I would like to use date.now() to find the start time and date.now() to get the current time and subtract the two to get the elapsed time in javascript?
Here is one I just built, Press "Run code snippet" at the bottom to test it out. Comment if you need further explanation.
var prevTime, stopwatchInterval, elapsedTime = 0;
var updateTime = function () {
var tempTime = elapsedTime;
var milliseconds = tempTime % 1000;
tempTime = Math.floor(tempTime / 1000);
var seconds = tempTime % 60;
tempTime = Math.floor(tempTime / 60);
var minutes = tempTime % 60;
tempTime = Math.floor(tempTime / 60);
var hours = tempTime % 60;
var time = hours + " : " + minutes + " : " + seconds + "." + milliseconds;
$("#time").text(time);
};
$("#startButton").click(function () {
if (!stopwatchInterval) {
stopwatchInterval = setInterval(function () {
if (!prevTime) {
prevTime = Date.now();
}
elapsedTime += Date.now() - prevTime;
prevTime = Date.now();
updateTime();
}, 50);
}
});
$("#pauseButton").click(function () {
if (stopwatchInterval) {
clearInterval(stopwatchInterval);
stopwatchInterval = null;
}
prevTime = null;
});
$("#resetButton").click(function () {
$("#pauseButton").click();
elapsedTime = 0;
updateTime();
});
$(document).ready(function () {
updateTime();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Time: <span id="time"></span><br>
<button id="startButton">Start</button>
<button id="pauseButton">Pause</button>
<button id="resetButton">Reset</button>
I didn't see Winestone's answer so I made an example in jsFiddle.
In a nutshell anyway:
var start=Date.now(),
stop=Date.now(),
diff=stop-start;
All the remaining fiddling you may need is for formatting time in milliseconds decently, and get the wanted delay between start and stop.
I want to use a simple countdown timer starting at 30 seconds from when the function is run and ending at 0. No milliseconds. How can it be coded?
var count=30;
var counter=setInterval(timer, 1000); //1000 will run it every 1 second
function timer()
{
count=count-1;
if (count <= 0)
{
clearInterval(counter);
//counter ended, do something here
return;
}
//Do code for showing the number of seconds here
}
To make the code for the timer appear in a paragraph (or anywhere else on the page), just put the line:
<span id="timer"></span>
where you want the seconds to appear. Then insert the following line in your timer() function, so it looks like this:
function timer()
{
count=count-1;
if (count <= 0)
{
clearInterval(counter);
return;
}
document.getElementById("timer").innerHTML=count + " secs"; // watch for spelling
}
I wrote this script some time ago:
Usage:
var myCounter = new Countdown({
seconds:5, // number of seconds to count down
onUpdateStatus: function(sec){console.log(sec);}, // callback for each second
onCounterEnd: function(){ alert('counter ended!');} // final action
});
myCounter.start();
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
So far the answers seem to rely on code being run instantly. If you set a timer for 1000ms, it will actually be around 1008 instead.
Here is how you should do it:
function timer(time,update,complete) {
var start = new Date().getTime();
var interval = setInterval(function() {
var now = time-(new Date().getTime()-start);
if( now <= 0) {
clearInterval(interval);
complete();
}
else update(Math.floor(now/1000));
},100); // the smaller this number, the more accurate the timer will be
}
To use, call:
timer(
5000, // milliseconds
function(timeleft) { // called every step to update the visible countdown
document.getElementById('timer').innerHTML = timeleft+" second(s)";
},
function() { // what to do after
alert("Timer complete!");
}
);
Here is another one if anyone needs one for minutes and seconds:
var mins = 10; //Set the number of minutes you need
var secs = mins * 60;
var currentSeconds = 0;
var currentMinutes = 0;
/*
* The following line has been commented out due to a suggestion left in the comments. The line below it has not been tested.
* setTimeout('Decrement()',1000);
*/
setTimeout(Decrement,1000);
function Decrement() {
currentMinutes = Math.floor(secs / 60);
currentSeconds = secs % 60;
if(currentSeconds <= 9) currentSeconds = "0" + currentSeconds;
secs--;
document.getElementById("timerText").innerHTML = currentMinutes + ":" + currentSeconds; //Set the element id you need the time put into.
if(secs !== -1) setTimeout('Decrement()',1000);
}
// Javascript Countdown
// Version 1.01 6/7/07 (1/20/2000)
// by TDavid at http://www.tdscripts.com/
var now = new Date();
var theevent = new Date("Sep 29 2007 00:00:01");
var seconds = (theevent - now) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
ID = window.setTimeout("update();", 1000);
function update() {
now = new Date();
seconds = (theevent - now) / 1000;
seconds = Math.round(seconds);
minutes = seconds / 60;
minutes = Math.round(minutes);
hours = minutes / 60;
hours = Math.round(hours);
days = hours / 24;
days = Math.round(days);
document.form1.days.value = days;
document.form1.hours.value = hours;
document.form1.minutes.value = minutes;
document.form1.seconds.value = seconds;
ID = window.setTimeout("update();", 1000);
}
<p><font face="Arial" size="3">Countdown To January 31, 2000, at 12:00: </font>
</p>
<form name="form1">
<p>Days
<input type="text" name="days" value="0" size="3">Hours
<input type="text" name="hours" value="0" size="4">Minutes
<input type="text" name="minutes" value="0" size="7">Seconds
<input type="text" name="seconds" value="0" size="7">
</p>
</form>
Just modified #ClickUpvote's answer:
You can use IIFE (Immediately Invoked Function Expression) and recursion to make it a little bit more easier:
var i = 5; //set the countdown
(function timer(){
if (--i < 0) return;
setTimeout(function(){
console.log(i + ' secs'); //do stuff here
timer();
}, 1000);
})();
var i = 5;
(function timer(){
if (--i < 0) return;
setTimeout(function(){
document.getElementsByTagName('h1')[0].innerHTML = i + ' secs';
timer();
}, 1000);
})();
<h1>5 secs</h1>
Expanding upon the accepted answer, your machine going to sleep, etc. may delay the timer from working. You can get a true time, at the cost of a little processing. This will give a true time left.
<span id="timer"></span>
<script>
var now = new Date();
var timeup = now.setSeconds(now.getSeconds() + 30);
//var timeup = now.setHours(now.getHours() + 1);
var counter = setInterval(timer, 1000);
function timer() {
now = new Date();
count = Math.round((timeup - now)/1000);
if (now > timeup) {
window.location = "/logout"; //or somethin'
clearInterval(counter);
return;
}
var seconds = Math.floor((count%60));
var minutes = Math.floor((count/60) % 60);
document.getElementById("timer").innerHTML = minutes + ":" + seconds;
}
</script>
For the sake of performances, we can now safely use requestAnimationFrame for fast looping, instead of setInterval/setTimeout.
When using setInterval/setTimeout, if a loop task is taking more time than the interval, the browser will simply extend the interval loop, to continue the full rendering. This is creating issues. After minutes of setInterval/setTimeout overload, this can freeze the tab, the browser or the whole computer.
Internet devices have a wide range of performances, so it's quite impossible to hardcode a fixed interval time in milliseconds!
Using the Date object, to compare the start Date Epoch and the current. This is way faster than everything else, the browser will take care of everything, at a steady 60FPS (1000 / 60 = 16.66ms by frame) -a quarter of an eye blink- and if the task in the loop is requiring more than that, the browser will drop some repaints.
This allow a margin before our eyes are noticing (Human = 24FPS => 1000 / 24 = 41.66ms by frame = fluid animation!)
https://caniuse.com/#search=requestAnimationFrame
/* Seconds to (STRING)HH:MM:SS.MS ------------------------*/
/* This time format is compatible with FFMPEG ------------*/
function secToTimer(sec){
const o = new Date(0), p = new Date(sec * 1000)
return new Date(p.getTime()-o.getTime()).toString().split(" ")[4] + "." + p.getMilliseconds()
}
/* Countdown loop ----------------------------------------*/
let job, origin = new Date().getTime()
const timer = () => {
job = requestAnimationFrame(timer)
OUT.textContent = secToTimer((new Date().getTime() - origin) / 1000)
}
/* Start looping -----------------------------------------*/
requestAnimationFrame(timer)
/* Stop looping ------------------------------------------*/
// cancelAnimationFrame(job)
/* Reset the start date ----------------------------------*/
// origin = new Date().getTime()
span {font-size:4rem}
<span id="OUT"></span>
<br>
<button onclick="origin = new Date().getTime()">RESET</button>
<button onclick="requestAnimationFrame(timer)">RESTART</button>
<button onclick="cancelAnimationFrame(job)">STOP</button>
You can do as follows with pure JS. You just need to provide the function with the number of seconds and it will do the rest.
var insertZero = n => n < 10 ? "0"+n : ""+n,
displayTime = n => n ? time.textContent = insertZero(~~(n/3600)%3600) + ":" +
insertZero(~~(n/60)%60) + ":" +
insertZero(n%60)
: time.textContent = "IGNITION..!",
countDownFrom = n => (displayTime(n), setTimeout(_ => n ? sid = countDownFrom(--n)
: displayTime(n), 1000)),
sid;
countDownFrom(3610);
setTimeout(_ => clearTimeout(sid),20005);
<div id="time"></div>
Based on the solution presented by #Layton Everson I developed a counter including hours, minutes and seconds:
var initialSecs = 86400;
var currentSecs = initialSecs;
setTimeout(decrement,1000);
function decrement() {
var displayedSecs = currentSecs % 60;
var displayedMin = Math.floor(currentSecs / 60) % 60;
var displayedHrs = Math.floor(currentSecs / 60 /60);
if(displayedMin <= 9) displayedMin = "0" + displayedMin;
if(displayedSecs <= 9) displayedSecs = "0" + displayedSecs;
currentSecs--;
document.getElementById("timerText").innerHTML = displayedHrs + ":" + displayedMin + ":" + displayedSecs;
if(currentSecs !== -1) setTimeout(decrement,1000);
}
// Javascript Countdown
// Version 1.01 6/7/07 (1/20/2000)
// by TDavid at http://www.tdscripts.com/
var now = new Date();
var theevent = new Date("Nov 13 2017 22:05:01");
var seconds = (theevent - now) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
ID = window.setTimeout("update();", 1000);
function update() {
now = new Date();
seconds = (theevent - now) / 1000;
seconds = Math.round(seconds);
minutes = seconds / 60;
minutes = Math.round(minutes);
hours = minutes / 60;
hours = Math.round(hours);
days = hours / 24;
days = Math.round(days);
document.form1.days.value = days;
document.form1.hours.value = hours;
document.form1.minutes.value = minutes;
document.form1.seconds.value = seconds;
ID = window.setTimeout("update();", 1000);
}
<p><font face="Arial" size="3">Countdown To January 31, 2000, at 12:00: </font>
</p>
<form name="form1">
<p>Days
<input type="text" name="days" value="0" size="3">Hours
<input type="text" name="hours" value="0" size="4">Minutes
<input type="text" name="minutes" value="0" size="7">Seconds
<input type="text" name="seconds" value="0" size="7">
</p>
</form>
My solution works with MySQL date time formats and provides a callback function. on complition.
Disclaimer: works only with minutes and seconds, as this is what I needed.
jQuery.fn.countDownTimer = function(futureDate, callback){
if(!futureDate){
throw 'Invalid date!';
}
var currentTs = +new Date();
var futureDateTs = +new Date(futureDate);
if(futureDateTs <= currentTs){
throw 'Invalid date!';
}
var diff = Math.round((futureDateTs - currentTs) / 1000);
var that = this;
(function countdownLoop(){
// Get hours/minutes from timestamp
var m = Math.floor(diff % 3600 / 60);
var s = Math.floor(diff % 3600 % 60);
var text = zeroPad(m, 2) + ':' + zeroPad(s, 2);
$(that).text(text);
if(diff <= 0){
typeof callback === 'function' ? callback.call(that) : void(0);
return;
}
diff--;
setTimeout(countdownLoop, 1000);
})();
function zeroPad(num, places) {
var zero = places - num.toString().length + 1;
return Array(+(zero > 0 && zero)).join("0") + num;
}
}
// $('.heading').countDownTimer('2018-04-02 16:00:59', function(){ // on complete})
var hr = 0;
var min = 0;
var sec = 0;
var count = 0;
var flag = false;
function start(){
flag = true;
stopwatch();
}
function stop(){
flag = false;
}
function reset(){
flag = false;
hr = 0;
min = 0;
sec = 0;
count = 0;
document.getElementById("hr").innerHTML = "00";
document.getElementById("min").innerHTML = "00";
document.getElementById("sec").innerHTML = "00";
document.getElementById("count").innerHTML = "00";
}
function stopwatch(){
if(flag == true){
count = count + 1;
setTimeout( 'stopwatch()', 10);
if(count ==100){
count =0;
sec = sec +1;
}
}
if(sec ==60){
min = min +1 ;
sec = 0;
}
if(min == 60){
hr = hr +1 ;
min = 0;
sec = 0;
}
var hrs = hr;
var mins = min;
var secs = sec;
if(hr<10){
hrs ="0" + hr;
}
if(min<10){
mins ="0" + min;
}
if(sec<10){
secs ="0" + sec;
}
document.getElementById("hr").innerHTML = hrs;
document.getElementById("min").innerHTML = mins;
document.getElementById("sec").innerHTML = secs;
document.getElementById("count").innerHTML = count;
}