I am trying to create a countdown website which runs a set of schedules as countdowns one after another. Each schedule is an array of a pair of strings which represent the start time and end time of each schedule.
Expected Behaviour:
I want the second schedule to start when the first one ends.
Current Behaviour:
After the first schedule is completed, the date shown on the webpage shows NaN for all the values.
Please help me understand what I am doing wrong as I am new to programming.
Codepen of Minimum Complete Verifiable Example [You may have to change the start time and end times of the schedules to be in the future depending on when you open it to reproduce the issue]
Code Sample:
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
clock.style.display = 'block';
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
// var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', schedule);
var schedule = [
['2018-05-01', '2018-05-02 13:36:00'],
['2018-05-02 13:36:01', '2018-05-09']
];
// iterate over each element in the schedule
for(var i=0; i<schedule.length; i++){
var startDate = schedule[i][0];
var endDate = schedule[i][1];
// put dates in milliseconds for easy comparisons
var startMs = Date.parse(startDate);
var endMs = Date.parse(endDate);
var currentMs = Date.parse(new Date());
// if current date is between start and end dates, display clock
if(endMs > currentMs && currentMs >= startMs ){
initializeClock('clockdiv', endDate);
}
}
The problem I think is mainly in two areas:
The for loop runs only once so the second schedule is never started after the first one ends (the for loop would have obviously finished executing and does not startup again). That loop should ideally run again once the first schedule ends.
The function to clear the timeout should be moved before the DOM update as the function getTimeRemaining may return inconsistent values when the schedule is over.
Solutions:
Wrap the schedule start code in a function startNewScheduleIfNeeded and run that new function each time a schedule ends and we clear the timer
Move the check to see if we should clear the timer above the DOM update in updateClock to avoid NaN values
Sample Code:
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
total: t,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
clock.style.display = "block";
var daysSpan = clock.querySelector(".days");
var hoursSpan = clock.querySelector(".hours");
var minutesSpan = clock.querySelector(".minutes");
var secondsSpan = clock.querySelector(".seconds");
function updateClock() {
var t = getTimeRemaining(endtime);
// Solution Part 2: Move check before DOM update and return early if needed
if (t.total <= 0) {
clearInterval(timeinterval);
// Schedule has ended, run function to start another if needed.
startNewScheduleIfNeeded();
return;
}
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ("0" + t.hours).slice(-2);
minutesSpan.innerHTML = ("0" + t.minutes).slice(-2);
secondsSpan.innerHTML = ("0" + t.seconds).slice(-2);
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
// var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
//initializeClock('clockdiv', schedule);
// Solution Part 1: Wrap schedule start in a function to resuse when schedules end
function startNewScheduleIfNeeded() {
var schedule = [
["2018-05-03", "2018-05-03 11:17:00"],
["2018-05-03 11:17:00", "2018-05-09"]
];
// iterate over each element in the schedule
for (var i = 0; i < schedule.length; i++) {
var startDate = schedule[i][0];
var endDate = schedule[i][1];
// put dates in milliseconds for easy comparisons
var startMs = Date.parse(startDate);
var endMs = Date.parse(endDate);
var currentMs = Date.parse(new Date());
// if current date is between start and end dates, display clock
if (endMs > currentMs && currentMs >= startMs) {
initializeClock("clockdiv", endDate);
}
}
}
startNewScheduleIfNeeded();
Other observations:
there was a random call to initializeClock which I have commented out
You only need to use Date.parse if your input is a string (like your schedule list). calling Date.parse(new Date()) is redundant. You can just use new Date(). Also, Date.parse DOES NOT return an integer (milliseconds). It returns a Date object which gets casted to a number when you do comparison like <
The end time of one schedule must be equal to the start time in the next schedule for this method to work. If you have gaps (even one second) the function to start the schedule will execute before the check to see if the current time is between the start time and end time can pass. (in the example in your question, end time of first schedule is '2018-05-02 13:36:00' and the start time for the next one is '2018-05-02 13:36:01'. This won't work - the start time of the second schedule has to be '2018-05-02 13:36:00').
Related
Countdown works fine but I need to output Text for exaple...
If 1 day is show then output Day if more days then Days, the same with hours, minutes and seconds..
function getTimeRemaining(endtime) {
const total = Date.parse(endtime) - Date.parse(new Date());
const seconds = Math.floor((total / 1000) % 60);
const minutes = Math.floor((total / 1000 / 60) % 60);
const hours = Math.floor((total / (1000 * 60 * 60)) % 24);
const days = Math.floor(total / (1000 * 60 * 60 * 24));
return {
total,
days,
hours,
minutes,
seconds
};
}
function initializeClock(id, endtime) {
function updateClock() {
const t = getTimeRemaining(endtime);
document.querySelector('.days').innerHTML = t.days;
document.querySelector('.hours').innerHTML = t.hours;
document.querySelector('.mins').innerHTML = t.minutes;
document.querySelector('.secs').innerHTML = ('0' + t.seconds).slice(-2);
if(t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
const timeinterval = setInterval(updateClock, 1000);
}
const countdown = "November 18 2022 19:00:00";
initializeClock("#codo", countdown);
1 Days 2 Hours 1 Minute 30 Seconds
I tried eg:
if(days > 1) { var day = 'Days'; } else { var day = 'Day'; }
But where exactly do I have to install it to output the text, I've tried a few things but non-stop initialize error given.
updateClock sets the output, specifically the 4 lines begining with document.querySelector. They set the content of 4 elements in your HTML.
function updateClock() {
const t = getTimeRemaining(endtime);
/* determine plural/singular word */
const days = t.days>1?" days":" day"
const hours = t.hours>1?" hours":" hour"
const minutes = t.minutes>1?" minutes":" minute"
const seconds = t.seconds>1?" seconds":" second"
/* append word to value */
document.querySelector('.days').innerHTML = t.days + days;
document.querySelector('.hours').innerHTML = t.hours + hours;
document.querySelector('.mins').innerHTML = t.minutes + minutes;
document.querySelector('.secs').innerHTML = ('0' + t.seconds).slice(-2) + seconds;
if(t.total <= 0) {
clearInterval(timeinterval);
}
}
innerHTML as the name suggests, sets the HTML inside the element. (as a string).
element.innerHTML = `Hello <div class="smallWord">World</div>`
I have ecommerce website. In that for same day delivery need to order before 11. So before 30 minutes of the end time(i.e. 11) i want to show that timer section.
Below code I am trying But getting issue how to set timer functionality.
setInterval(function(){
var secs = 1800;
var date = new Date;
// date.setTime(result_from_Date_getTime);
var seconds = date.getSeconds();
var minutes = date.getMinutes();
var hour = date.getHours();
console.log("Hour"+hour+"Minutes"+minutes+"seconds"+seconds);
// console.log(minutes);
// console.log(seconds);
if(hour == 10 && minutes>=30)
{
var mins = secs / 60;
console.log("Timer"+mins);
$('.top-header-content1').removeClass('hide-ticker1');
}
else if (hour >= 11){
console.log("hii11");
$('.top-header-content1').addClass('hide-ticker1');
}
secs--;
},1000);
If anyone have a idea , how to add time please let me know
Hi you use this code below:
/// the counting date
var countDownDate = new Date("Jan 5, 2024 15:37:25").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is finished
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
<p id="demo"></p>
The following code will start a setInterval() in which during a time window between 10:30h and 11:00h a countdown will be shown. Before 10:30h and after 11:00h different messages are shown. And after 11:00h the setInterval is cleared.
// div for output on page:
const demo=document.getElementById("demo"),
// today's date
today = new Date();
today.setHours(11);today.setMinutes(0);today.setSeconds(0);
today.intv=setInterval(checkTime,1000);
function checkTime(){
const now=new Date();
if (now>today) {
demo.textContent="Order today for tomorrow's delivery.";
clearInterval(today.intv);
}
else if (now>(today-1800000)){
let tsec=Math.floor((today-now)/1000),
sec=tsec%60,
min=(tsec-sec)/60;
demo.textContent=`${min} minutes and ${sec} seconds left if you want to order for today's delivery.`;
} else
demo.textContent="Order now for today's delivery!"
}
<p id="demo"></p>
My friend has given me files of his website to clone and make my own version, everything works as intended except for this time interval function. It works perfectly fine on my friends website, however on mine I found the countdown goes to zero, refreshes the page and doesn't reset, causing the page to reload constantly
var x = setInterval(function() {
var thing = parseInt($('#quest_reset').val());
thing = thing * 1000;
var now = new Date().getTime();
var distance = thing - now;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("hours").innerHTML = hours
document.getElementById("minutes").innerHTML = minutes
document.getElementById("seconds").innerHTML = seconds
if (distance < 0) {
console.log(distance)
clearInterval(x);
document.getElementById("hours").innerHTML = 0
document.getElementById("minutes").innerHTML = 0
document.getElementById("seconds").innerHTML = 0
location.reload();
}
}, 1000);
The original value of thing is 1628380822, which would mean the value of #quest_reset would also be 1628380822 I found the value of now is much larger than thing
How come this works fine on my friends website but not on mine?
I guess that you code is fine, but here is my version. Instead of all the calculations you can use the Date object.
Here I define a future date by creating a new date and add 20 seconds to it. This is the timestamp that you compare against. This could also be a fixed number -- like the thing that you refer to.
In the function checktime the ´diffdate´ is the difference between the future date and now. If diff is less then 0 diffdate is set to 0, the interval is cleared and you can then reload or whatever. As the last thing (instead of repeating the same code) in the function the hour, minutes and seconds are set in the HTML elements.
All timestamps in the browser will start at Jan 01 1970 00:00:00 GMT. Try to console.log(new Date(0)). Your thing is a number of milliseconds -- probably the difference or a period defined by something. That is why thing is mush smaller than new Date().getTime() because that is the number of milliseconds from Jan 01 1970 and until now.
var h = document.getElementById("hours");
var m = document.getElementById("minutes");
var s = document.getElementById("seconds");
var futuredate = new Date();
futuredate.setSeconds(futuredate.getSeconds() + 20);
const checktime = function() {
let now = new Date();
let diffdate = new Date(futuredate - now);
let zero = new Date(0);
if (diffdate.getTime() < 0) {
diffdate = new Date(0);
clearInterval(x);
console.log('reload!');
}
h.innerText = diffdate.getHours() - zero.getHours();
m.innerText = diffdate.getMinutes() - zero.getMinutes();
s.innerText = diffdate.getSeconds() - zero.getSeconds();
};
var x = setInterval(checktime, 1000);
<div>
<span id="hours"></span>
<span id="minutes"></span>
<span id="seconds"></span>
</div>
I'm trying to make this count down not reset on load or refresh. Can anyone help me with this? I have heard I can use local storage but surly I will need to change this code to be server sided with PHP and MySQL. If you do have any resources which show you the PHP version could you send them to me or post as an answer?
var updateTimer = function() {
timer = localStorage.getItem('timer') || 0;
if ( timer === 0 ) {
$("div#timer").html("Timer is unset");
} else {
timer--;
localStorage.setItem('timer', timer);
$("div#timer").html(timer);
}
};
$(function() {
setInterval(updateTimer, 1000);
$("#start").click( function() {
localStorage.setItem('timer', 500);
});
});
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
Thank you
If you want to completely avoid server sided coding, you can save values using Cookies.
In javascript this is easily done by document.cookie = "yourValues, expiryDate".
JQuery also has some nice functions to handle cookies.
You may want to adjust your script to calculate the passed time between loads or not having the clock run, but that is optional.
http://www.w3schools.com/js/js_cookies.asp <- Here is a simple tutorial on how to use them.
With php you can use the cookie's to achieve the same.
setcookie($timer); // Set timer
$_COOKIE['timer']; // Get timer
You can start inserting into mysql in every refresh but use $_COOKIE to show. Mysql is just for tracking and getting correct time after refresh the page.
mysql_query("UPDATE table SET timer = '$timer'"); // Inserting every refresh
So when page loads either get form stored cookie or retrieve from mysql table
But COOKIES will be faster than using only mysql method(It won't work properly as it need to request every second)
I'm trying to create a countdown counter that should countdown for 24 hours, displaying the days, the hours, the minutes and the seconds. The question is that I want to make it somehow save the progress. For example, I put the countdown to start from now till tomorrow the same time (24 hours) and when a user comes in my site after 2 hours the counter should start from 22 hours for that user and if the user closes the site and then comes back after 2 hours the counter should start from 20 hours for that user. I hope it's clear enough. I found that if that is possible it could be done using cookies, but I'm not sure how it should be done... If anyone could help it will be great! :3
Here is my code so far:
HTML:
<div id="clockdiv">
<span class="days"></span>
<span class="hours"></span>
<span class="minutes"></span>
<span class="seconds"></span>
</div>
JavaScript
// if there's a cookie with the name myClock, use that value as the deadline
if(document.cookie && document.cookie.match('myClock')){
// get deadline value from cookie
var deadline = document.cookie.match(/(^|;)myClock=([^;]+)/)[2];
}
// otherwise, set a deadline 10 minutes from now and
// save it in a cookie with that name
else{
// create deadline 10 minutes from now
var timeInMinutes = 1380;
var currentTime = Date.parse(new Date());
var deadline = new Date(currentTime + timeInMinutes*60*1000);
// store deadline in cookie for future reference
document.cookie = 'myClock=' + deadline + '; path=/; domain=.optic2n.com';
}
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
initializeClock('clockdiv', deadline);
Thank you in advance for the help! :3
Best regards,
Tsvetko Krastev
It is possible I have missed something, but your code seems very complex for something so simple. Here is what I came up with:
HTML:
<div id="clockdiv">
<span id="d" class="days"></span>days
<span id="h" class="hours"></span>hrs
<span id="m" class="minutes"></span>mins
<span id="s" class="seconds"></span>secs
</div>
Javascript:
var deadline = localStorage.getItem('dl') ? parseInt(localStorage.getItem('dl')) : (Date.now() + 86400000);
var delay = null;
// Good spot to do checks for 24hrs has passed already here
localStorage.setItem('dl',deadline);
function render() {
if (delay) {
clearTimeout(delay);
delay = null;
}
var diff = (deadline - Date.now()) / 1000;
document.getElementById('d').innerHTML = Math.floor(diff / 86400);
document.getElementById('h').innerHTML = Math.floor(diff / 3600);
document.getElementById('m').innerHTML = Math.floor((diff / 60) % 60);
document.getElementById('s').innerHTML = Math.floor(diff % 60);
delay = setTimeout(render,1000);
}
render();
NOTE: There are no checks for what to do after 24 hours.