I have a webinar that runs every 15 minutes of every hour of the day (EG: 11:00, 11:15, 11:30 & 11:45).
I'd like a countdown timer that shows the remaining minutes until the next start time and all I can find from days of searches and trying to figure this out myself is an hourly countdown.
My question is, how do I update this code for be every 15 minutes not every 60.
<script>
/* Return minutes and seconds to next hour
** #returns {Object} minutes: minutes remaining
** seconds: seconds remaining
*/
function getTimeRemaining() {
var t = Date.now();
var seconds = (60 - Math.floor(t % 6e4 / 1e3)) % 60;
var minutes = 60 - Math.ceil(t % 3.6e6 / 6e4) + (seconds? 0:1);
return {
'minutes': ('0' + minutes).slice(-2),
'seconds': ('0' + seconds).slice(-2) };
}
// Simple show remaining function
function showRemaining() {
var r = getTimeRemaining();
document.getElementById('clock').textContent = (r.minutes + ':' + ('0' + r.seconds).slice(-2));
// Run again just after next full second
setTimeout(showRemaining, 1020 - (Date.now() % 1000));
}
showRemaining();
</script>
That solution seems overly complicated and you should be definitely using setInterval for a task where you have to update something every x seconds, recursively calling setTimeout is a bad idea. Here is a solution that is much more understandable:
const runEvery = 15 * 60; // 15 minutes in seconds
const showRemaining = () => {
// get current time in seconds and find when the next run starts in seconds
const seconds = Math.round(Date.now() / 1000);
const nextRun = runEvery * Math.ceil(seconds / runEvery);
const timeLeft = nextRun - seconds;
const minutesLeft = Math.floor(timeLeft / 60);
const secondsLeft = timeLeft % 60;
document.getElementById('clock').textContent = minutesLeft + ':' + ('0' + secondsLeft).slice(-2);
}
showRemaining();
setInterval(showRemaining, 1000);
<div id="clock"></div>
Related
I have an external JS file, with the function time().
In my HTML, I have
<p id="sentence"> </p>
<script src="javascript.js" type="text/javascript">
time();
</script>
The time function calculates how much time there is left until a certain hour, I checked with console.log() and the algorithm is good.
I wanna display the output to <p>
I tried:
document.getElementByID("sentence").innerHTML= ("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
What am I missing?
Edit: the time function as requested:
function time() {
let date = new Date();
date.setHours(16);
date.setMinutes(0);
let day = date.getDate();
date.setSeconds(0)
date.setMilliseconds(0); // set happy hour for the day
let interval = date - Date.now(); //calculate ms between current time and happy hour time
//case when happy hour is later than current date, on the same day
if (interval > 0) {
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000)
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000);
document.getElementByid("sentence").innerHTML= ("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
} else if (interval < 0 && interval < -3600000) { //happy hour gone, time left until it starts tomorrow
date.setDate(++day);
console.log(date);
interval = date - Date.now();
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000);
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000)
document.getElementByid("sentence").innerHTML= ("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
} else { //happy hour started, but didn't finish yet
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000)
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000);
document.getElementByid("sentence").innerHTML= ("Happy hour finished in " + hour + ":" + minutes + ":" + seconds);
}
}
Your error are bunch of typos as mentioned in the comments.
All you had to do was: use getElementById instead of getElementByID or getElementByid. (notice how 'Id' is spelt)
Here is a sample working code:
function time() {
let date = new Date();
date.setHours(16);
date.setMinutes(0);
let day = date.getDate();
date.setSeconds(0)
date.setMilliseconds(0); // set happy hour for the day
let interval = date - Date.now(); //calculate ms between current time and happy hour time
//case when happy hour is later than current date, on the same day
if (interval > 0) {
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000)
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000);
document.getElementById("sentence").innerHTML = ("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
} else if (interval < 0 && interval < -3600000) { //happy hour gone, time left until it starts tomorrow
date.setDate(++day);
console.log(date);
interval = date - Date.now();
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000);
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000)
document.getElementById("sentence").innerHTML = ("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
} else { //happy hour started, but didn't finish yet
const hour = Math.floor(interval / 3600000);
interval -= 3600000 * Math.floor(interval / 3600000);
const minutes = Math.floor(interval / 60000)
interval -= 60000 * Math.floor(interval / 60000);
const seconds = Math.floor(interval / 1000);
document.getElementById("sentence").innerHTML = ("Happy hour finished in " + hour + ":" + minutes + ":" + seconds);
}
}
time()
<p id="sentence"></p>
Assuming javascript.js is a file you need to load, containing the definition of the time function, then this will not work:
<script src="javascript.js" type="text/javascript">
time();
</script>
A script tag with a src attribute will simply load the script from the given URL, and ignore any contents.
It looks like you want to load the file and then call the function: in that case you can do it like this:
<script src="javascript.js" type="text/javascript"></script>
<script>time();</script>
You should use DOM node it's pretty easy especially for your certain use,
Html will be as following
<div id="div1">
</div>
<script src="javascript.js" type="text/javascript">
time();
</script>
Javascript:
var para = document.createElement("p");
var text = document.createTextNode("Happy hour starts in " + hour + ":" + minutes + ":" + seconds);
para.appendChild(text);
var element = document.getElementById("div1");
element.appendChild(para);
Check https://www.w3schools.com/js/js_htmldom_nodes.asp to understand it even better.
Try this instead or pass your function that get detail or hours minutes and seconds
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Time</title>
</head>
<body>
<p id = "sentence"> </p>
<script>
const hour = new Date().getHours();
const minutes = new Date().getMinutes();
const seconds = new Date().getSeconds();
document.getElementById('sentence').innerHTML = "Happy hour starts in " + hour + ":" + minutes + ":" + seconds;
</script>
</body>
</html>
Run the snippet for the output
As of now, I've written a script for a timer to countdown to a specific day. The problem is that the moment you refresh the browser, it takes 1 second for it to appear as opposed to it appearing instantly.
I actually did figure out a way to make it appear instantly but I had to repeat the block of code with countDownDate, now, timeDifference, oneDay, days, hours, minutes, seconds and document.getElementById("timer").innerHTML = ...; by placing it directly on top of timer() which's totally inefficient.
In my attempt below, the countdown appears about one second upon the browser refreshing but I want it to appear instantly. My goal here is to create reusable code.
What am I doing wrong and how can I fix it?
Here's the html:
<h1 id="timer"></h1>
Here's the js:
function conversion() {
var countDownDate = new Date("June 1, 2019 24:00:00");
var now = new Date().getTime();
var timeDifference = countDownDate - now;
var oneDay = 1000 * 60 * 60 * 24;
var days = Math.floor(timeDifference / (oneDay));
var hours = Math.floor((timeDifference % (oneDay)) / (1000 * 60 * 60));
var minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
document.getElementById("timer").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
function timerCountdown() {
var timer = setInterval(function() {
conversion();
if(timeDifference < 0) {
clearInterval(timer);
document.getElementById("timer").innerHTML = "Timer's over.";
}
}, 1000);
}
timerCountdown();
Put the setInterval callback into a variable, and both call setInterval with that function and call it immediately on pageload:
function timerCountdown() {
var timer = setInterval(intervalCb, 1000);
function intervalCb() {
conversion();
if(timeDifference < 0) {
clearInterval(timer);
document.getElementById("timer").innerHTML = "Timer's over.";
}
}
intervalCb();
}
timerCountdown();
Just call conversion() immeadiately.
I alreay have some code for a countdown, but would like to make it pause for some hours when at 0 (with a text displayed), and then starts again for 14 days.
<script type="text/JavaScript">
var Display=document.getElementById("Counter");
function Countdown() {
var date1 = new Date();
var date2 = new Date ("Oct 20 20:00:00 2017");
var sec = (date2 - date1) / 1000;
var n = 24 * 3600;
if (sec > 0) {
j = Math.floor (sec / n);
h = Math.floor ((sec - (d * n)) / 3600);
mn = Math.floor ((sec - ((d * n + h * 3600))) / 60);
sec = Math.floor (sec - ((d * n + h * 3600 + mn * 60)));
Affiche.innerHTML = "Next game in : " + d +" d "+ h +" h "+ mn +" min "+ sec + " s ";
window.status = "Remaining time : " + d +" d "+ h +" h "+ mn +" min "+ sec + " s ";
}
tCountdown=setTimeout ("Countdown();", 1000);
}
Countdown();
</script>
So to sum up:
1. The countdown reach 0
2. It blocks for 4 hours and display a text ("We are currently playing")
3. It starts again for around 14 days.
I am thinking of something like this to start again the countdown:
var dateX = var date2 + (a length of time around 14 days)
Am I right?
Can I do this only with Javascript?
I broke it up into a bunch of functions so you can reason about it. If you want to test it, you can set the initial seconds in the sec variable to something small, like 10, and then you can also set the second argument in setTimeout to something small, like 10.
<div id="counter"></div>
<script>
// initialize
var first_target_date = new Date ("Oct 20 20:00:00 2017");
var sec = calcSecDiff(new Date(), first_target_date);
var counter = document.getElementById("counter");
var timeout; // we will update this global variable when we want to stop the whole thing
// start the countdown
countdown();
// do it again every second
var interval = setInterval(function(){
countdown();
}, 1000);
function countdown() {
counter.innerHTML = parseTime(sec);
// decrement the second
sec--;
// if we get to 0
if (sec < 0) {
clearInterval(interval);
counter.innerHTML = "We are currently playing";
if (timeout) return; // it's over
var timeout = setTimeout(function(){
sec = daysToSec(14); // reset the seconds to 14 days away
var interval = setInterval(function(){
countdown();
}, 1000);
}, hrsToMs(4)); // wait four hours before counting down again
};
}
// returns days, hours, minutes, and seconds from seconds
// see https://stackoverflow.com/questions/13903897/javascript-return-number-of-days-hours-minutes-seconds-between-two-dates
function parseTime(sec){
// calculate (and subtract) whole days
var days = Math.floor(sec / 86400);
sec -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(sec / 3600) % 24;
sec -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(sec / 60) % 60;
sec -= minutes * 60;
// what's left is seconds
var seconds = sec % 60;
return days + " days, " + hours + " hours, " + minutes + " minutes, " + seconds + " seconds";
}
// calculates the difference between two dates in seconds
function calcSecDiff(date1, date2){
return Math.round((date2 - date1) / 1000);
}
// converts hours to milliseconds
function hrsToMs(hrs){
return hrs * 60 * 60 * 1000;
}
// converts days to seconds
function daysToSec(days){
return days * 24 * 60 * 60;
}
</script>
I've got a function here that outputs seconds as days, minutes, and seconds, and I'd like it run once a second, and add one to the delta - giving a semi accurate difference between two dates.
$(document).ready(function() {
if ($("#time").length) {
var delta = document.getElementById('time').innerHTML;
function timer(delta) {
setInterval(function() {
// calculate (and subtract) whole days
var days = Math.floor(delta / 86400);
delta -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
// what's left is seconds
var seconds = delta % 60;
// console.log(minutes);
console.log(days + " " + hours + " " + minutes + " " + seconds)
timer(delta + 1)
}, 1000);
}
}
});
What do I need to change to achieve this? I have some familiarity with recursion - but not a lot, in all honesty.
Change 'setInterval' to 'setTimeout'.
setInterval according to MDN:
Repeatedly calls a function or executes a code snippet, with a fixed
time delay between each call. Returns an intervalID.
Which means that it will run the once per 1000ms, and call the timer() function that will spawn another setInterval. Now you'll have to 2 setInterval running, 4 after 1000ms, etc...
setTimeout on the other hand expires after it invokes the callback. The callback will execute, and start a new timer, and the cycle will continue.
var time = document.getElementById('time');
function timer(delta) {
setTimeout(function() {
// calculate (and subtract) whole days
var days = Math.floor(delta / 86400);
delta -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
// what's left is seconds
var seconds = delta % 60;
time.innerHTML = (days + " " + hours + " " + minutes + " " + seconds);
timer(delta + 1)
}, 1000);
}
timer(0);
<div id="time"></div>
You can continue to use setInterval() if you update the outer variable delta within your timer() function
var delta = document.getElementById('time').innerHTML;
function timer() {
// calculate (and subtract) whole days
var days = Math.floor(delta / 86400);
delta -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
// what's left is seconds
var seconds = delta % 60;
// console.log(minutes);
document.getElementById('result').innerHTML = days + " " + hours + " " + minutes + " " + seconds;
delta++;
}
setInterval(timer, 1000);
<div id="time">0</div>
<div id="result"></div>
Here's how I would write it out :
$(document).ready(function() {
function Timer(delta) {
// Local variables
var delta, intervalId;
this.start = function(initialDelta) {
if (!intervalId) {
delta = initialDelta;
intervalId = window.setInterval(function() {
// calculate (and subtract) whole days
var days = Math.floor(delta / 86400);
delta -= days * 86400;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
// what's left is seconds
var seconds = delta % 60;
// console.log(minutes);
console.log(days + " " + hours + " " + minutes + " " + seconds)
delta++;
})
}
}
this.stop = function() {
if (intervalId) {
window.clearInterval(intervalId);
}
}
}
if ($("#time").length) {
var timer = new Timer();
var delta = parseInt(document.getElementById('time').innerHTML);
timer.start(delta);
window.setTimeout(function() { timer.stop(); }, 5000);
}
});
Quick explanation : by using a constructor function Timer, you can isolate delta to each instance of Timer (like a private variable of a class in Java). By doing this, you avoid having to use recursion and your initial method using setInterval works perfectly well for this purpose, because every time the function is called, it can access and modify its own local delta.
This would allow you to start multiple timers, start them with different delta values, etc..
So, I have the below (seconds countdown) in good order. But! I am trying to add hours & minutes as apart of the count down as well. Ideally keeping the same structure, and just using pure JS. I would like the output to be:
There is X hours, X minutes, and X seconds remaining on this Sale!
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);
return;
}
document.getElementById("timer").innerHTML=count + " secs"; // watch for spelling
}
If the solution has to be a rewrite with jQuery or another library; that's fine. Just not preferable.
Cheers and Salutations for any help.
Something like this:
var count = 30;
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
function timer() {
count = count - 1;
if (count == -1) {
clearInterval(counter);
return;
}
var seconds = count % 60;
var minutes = Math.floor(count / 60);
var hours = Math.floor(minutes / 60);
minutes %= 60;
hours %= 60;
document.getElementById("timer").innerHTML = hours + "hours " + minutes + "minutes and" + seconds + " seconds left on this Sale!"; // watch for spelling
}
var totalSeconds = 3723; // lets say we have 3723 seconds on the countdown
// that's 1 hour, 2 minutes and 3 seconds.
var hours = Math.floor(totalSeconds / 3600 );
var minutes = Math.floor(totalSeconds % 3600 / 60);
var seconds = totalSeconds % 60;
var result = [hours, minutes, seconds].join(':');
console.log(result);
// 1:2:3
hours is seconds divided by the number of seconds in hour (3600) rounded down
minutes is the remainder of the above division, divided by the number of seconds in a minute (60), rounded down.
seconds is the remainder of total seconds divided by seconds in a minute.
Each calculation after hour has to use a modulus calculation to get the remainder, because you don't care about total time at that step, just progress to the next tick.
I would use a similar method to the others, but I wouldn't rely on setInterval / setTimeout as a timer, especially if users might be looking at the page for some time, as it tends to be inaccurate.
var endTime = new Date(2013, 10, 31).getTime() / 1000;
function setClock() {
var elapsed = new Date().getTime() / 1000;
var totalSec = endTime - elapsed;
var d = parseInt( totalSec / 86400 );
var h = parseInt( totalSec / 3600 ) % 24;
var m = parseInt( totalSec / 60 ) % 60;
var s = parseInt(totalSec % 60, 10);
var result = d+ " days, " + h + " hours, " + m + " minutes and " + s + " seconds to go!";
document.getElementById('timeRemaining').innerHTML = result;
setTimeout(setClock, 1000);
}
setClock();
This method calculates the difference between now and the date in the future each time it is run, thus removing any inaccuracies.
Here is an example: http://jsfiddle.net/t6wUN/1/