so for a while I ve been trying to implement a script that prints me the remaining time (countdown) to an specific day of the week (Sunday) at 16 h (4PM), my server date timezone is set to America/New_York (GMT-5).. so far I have this code, it is not working well, only when countdown remaining time is less/under than 1 day, script start showing negative values (like, -1 hour..) any help here? cheers
https://jsfiddle.net/v4wjbtus/
function plural(s, i) {
return i + ' ' + (i > 1 ? s + 's' : s);
}
function sundayDelta(offset) {
// offset is in hours, so convert to miliseconds
offset = offset ? offset * 60 * 60 * 1000 : 0;
var now = new Date(new Date().getTime() + offset);
var days = 7 - now.getDay() || 7;
var hours = 21 - now.getHours() || 24;
var minutes = 60 - now.getMinutes();
var seconds = 60 - now.getSeconds();
return [plural('day', days),
plural('hour', hours),
plural('minute', minutes),
plural('second', seconds)].join(' ');
}
// Save reference to the DIV
$refresh = jQuery('#refresh');
$refresh.text('News in ' + sundayDelta());
// Update DIV contents every second
setInterval(function() {
$refresh.text('News in ' + sundayDelta());
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="refresh" class="text-success" style="position: absolute;bottom: 0;"></div>
Since there are already examples of converting milliseconds duration to human-readable form, I instead created a mashup with your code and what I found.
For my tastes, I would further update this to not show a segment if the segment equals zero, so that it reads better.
// seed date, (ANY past sunday at 16:00)
var seed = new Date(2020, 11, 6, 16);
var target;
// pluralize/singularize
function plural(s, i) {
return i + ' ' + (i > 1 ? s + 's' : s);
}
// miliseconds to the next upcoming sunday 16:00
function timeToTarget() {
while (seed < new Date()) {
seed.setDate(seed.getDate()+7)
}
target = seed;
return Math.abs(seed - new Date());
}
// convert miliseconds duration to human readable
function msReadableDuration() {
var duration = timeToTarget();
var seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24),
days = Math.floor((duration / (24 * 60 * 60 * 1000) % 7));
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return [plural('day', days),
plural('hour', hours),
plural('minute', minutes),
plural('second', seconds)].join(', ');
}
// show seed date
$seed = jQuery('#seed');
$seed.text(seed.toString());
// Save reference to the DIV
$refresh = jQuery('#refresh');
$refresh.text('News in ' + msReadableDuration());
// Update DIV contents every second
setInterval(function() {
$refresh.text('News in ' + msReadableDuration());
}, 1000);
// show seed date (target is computed after timeToTarget executes)
$target = jQuery('#target');
$target.text(target.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="seed"></div>
<div id="target"></div>
<p id="refresh"></p>
And instead of using a seed date, you can further refine my snippet to have a function that simply looks for the next up-coming Sunday via something similar to this: https://codereview.stackexchange.com/a/33648
Related
Key variables to keep in mind:
This is set to simulate 11:00 PM.
var bt = "23:00";
This is set to simulate 8:00 AM.
var wt = "08:00";
The desired functionality:
The countdown timer starts every morning at 8:00 AM.
It counts down until 11:00 PM, every night.
Then it stays at 00:00:00.
In the morning, at 8:00 AM, it repeats the count-down, again.
This should happen forever.
What is actually happening:
Everything is working fine, except it is starting a 24 hour countdown at midnight, until 8:00 AM.
I have tried debugging this, and I suspect the error lies in what is calculated as the distance variable, making the code think that it is comparing against the next day, but I am not sure how to remedy this.
Here is the Codepen.
and here is my JS code:
$(document).ready(function () {
var bt = "23:00"; // 11:00 PM
var wt = "08:00"; // 08:00 AM
var dateNow = moment().format('MMM D, YYYY');
placeHolderDate = dateNow + " " + bt;
var timeNow = moment().format('HH:mm');
var countDownDate = new Date(placeHolderDate).getTime();
var countDownHourMin = (wt.split(":"));
// Update the count down every 1 second
var x = setInterval(function () {
// Get todays 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 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);
$("#countDown").val(hours + ":" + minutes + ":" + seconds);
// If the countdown is over, write some text
if (hours === 0 && minutes === 0 && seconds === 0) {
//clearInterval(x);
$("#countDown").val("00:00:00");
}
if (hours < 0 || minutes < 0 || seconds < 0) {
//clearInterval(x);
$("#countDown").val("00:00:00");
}
var timeNow = moment().format('HH:mm');
//console.log('Time Now:' + timeNow);
//console.log('Wake Time:' + wt);
if (timeNow === wt) {
clearInterval(x);
restartCountdown();
}
//console.log(hours + ":" + minutes + ":" + seconds);
}, 1000);
function restartCountdown() {
//log("restartCountdown Started!");
var bt = "23:00"; // 11:00 PM
var wt = "08:00"; // 08:00 AM
var dN = (moment().add(moment.duration({d: 1})).format('MMM D, YYYY'));
console.log('dn ' + dN);
var placeHolderDate = dN + " " + bt;
var countDownDate = new Date(placeHolderDate).getTime();
var countDownHourMin = (wt.split(":"));
// Update the count down every 1 second
var x = setInterval(function () {
// Get todays 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 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);
$("#countDown").val(hours + ":" + minutes + ":" + seconds);
// If the countdown is over, write some text
if (hours === 0 && minutes === 0 && seconds === 0) {
//clearInterval(x);
$("#countDown").val("00:00:00");
}
if (hours < 0 || minutes < 0 || seconds < 0) {
//clearInterval(x);
$("#countDown").val("00:00:00");
}
// console.log(hours + ":" + minutes + ":" + seconds);
}, 1000);
}
});
I have edited your code and created this codepen https://codepen.io/anon/pen/aabjEb?editors=0010. Please feel free to optimize the code since I have not done it. The idea was is check if time is between 8 AM and 11 PM. If yes show value else show 00:00:00. Also once the date changes, update the dates and now compute accordingly
$(document).ready(function () {
function countdown() {
var bt = "23:00", // 11:00 PM
wt = "08:00"; // 08:00 AM
var today = new Date(),
dd = today.getDate(),
mm = today.getMonth()+1,
yyyy = today.getFullYear();
var startTime = new Date(mm + '/' + dd + '/' + yyyy + ' ' + wt),
endTime = new Date(mm + '/' + dd + '/' + yyyy + ' ' + bt);
setInterval(function() {
var now = new Date();
var nowdd = today.getDate();
var nowTime = now.getTime();
if(dd !== nowdd) {
dd = nowdd;
var nowmm = now.getMonth() + 1,
nowyyyy = now.getFullYear();
startTime = new Date(dd + '/' + mm + '/' + yyyy + ' wt');
endTime = new Date(dd + '/' + mm + '/' + yyyy + ' bt');
}
if(nowTime > startTime && nowTime < endTime) {
// Find the distance between now and the count down date
var distance = endTime - nowTime;
// Time calculations for days, hours, minutes and seconds
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)),
seconds = Math.floor((distance % (1000 * 60)) / 1000);
$("#countDown").val(hours + ":" + minutes + ":" + seconds);
} else {
$("#countDown").val("00:00:00");
}
}, 1000);
}
countdown();
});
So I have an array of dates and want to get the current date and put it into a countdown clock
I have this code atm:
<script>
var dates = [
'24/5/2017',
'12/6/2017',
'14/6/2017',
'16/6/2017',
'20/6/2017',
'20/6/2017',
'22/6/2017',
'23/6/2017',
'26/6/2017'
];
function sortDates(dates) {
return dates.map(function(date) {
return new Date(date).getTime();
}).sort(function(a, b) {
return a - b;
});
}
var orderedDates = sortDates(dates);
document.getElementById("demoo").innerHTML = orderedDates
var nextDate = orderedDates.filter(function(date) {
return (var now = new Date().getTime(); - date) > 0;
})[0];
document.getElementById("demo").innerHTML = nextDate
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = nextDate - 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);
// Output the result in an element with id="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
</script>
<center><h2>Core Maths 2</h2><center>
This doesn't seem to do anything, so I don't really know what to do. at the moment it just comes up with NAN for the countdown
One problem is, that, for instance, new Date('24/5/2017') yields Invalid Date. I don't think this is a valid Date format recognized by new Date().
If you really need the format like this, you can do something like:
var dates = [
'24/5/2017', // past Date for testing
'12/6/2017',
'14/6/2017',
'16/6/2017',
'20/6/2017',
'20/6/2017',
'22/6/2017',
'23/6/2017',
'26/6/2017'
].map(function (d) {
var parts = d.split('/');
return new Date(parts[2], parts[1] - 1 /* january = 0 */, parts[0]);
});
so you end up having actual Date objects instead of strings by passing the parameters in a order to the Date constructor which it understands.
Another point: Since you can interpret a Date object as a Number (which yields the same as new Date().getTime(), namely the milliseconds since January 1, 1970), you can simply get the minimum using: Math.min.apply(Math, dates). So, your "next Date" (smallest timestamp which is not in the past) can simply been retrieved by var nextDate = new Date(Math.min.apply(Math, dates.filter(x => +x > Date.now())));
Below is a working snipppet which should do what you wanted.
var dates = [
'20/4/2017',
'24/5/2017',
'12/6/2017',
'14/6/2017',
'16/6/2017',
'20/6/2017',
'20/6/2017',
'22/6/2017',
'23/6/2017',
'26/6/2017'
].map(function (d) {
var parts = d.split('/');
return new Date(parts[2], parts[1] - 1 /* january = 0 */, parts[0]);
});
var nextDate = new Date(Math.min.apply(Math, dates.filter(x => +x > Date.now())));
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = nextDate - 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);
// Output the result in an element with id="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
<center><h2>Core Maths 2</h2><center>
<div id="demo"></div>
So I did your dirty work for you, all you needed to do is some debugging, putting some console logs here and there to find out what was going wrong, which was a couple of things.
1. Your date formats are messed up (at least for me).
Instead of typing '24/5/2017', type '5/24/2017' if you want it to go right when you pass it into a Date() constructor. You can validate this by doing this: console.log(new Date('24/5/2017'));
2. Your filter function was bad
You want the next date, though you check for now - date > 0 which means that only dates that were in past will work. Either use date - now > 0 or now - date < 0.
3. You made a typo
document.getElementById("demoo").innerHTML = orderedDates
Notice the extra 'o' in 'demoo'.
4. You used invalid syntax
var nextDate = orderedDates.filter(function(date) {
return (var now = new Date().getTime(); - date) > 0;
})[0];
This doesn't work because you cannot declare now like this. Extract the declaration of now to a line above the return statement as follows:
var nextDate = orderedDates.filter(function(date) {
var now = new Date().getTime();
return (now - date) < 0;
})[0];
If you apply all these corrections your countdown should work.
I searched everywhere but I'm not satisfied by the answer. At last I'm posting here to get the answer.
I have two datepicker and time picker textbox which displays 12:00 format with AM & PM.
Here I want to calculate the TOTAL time which includes number of days and given time.
I want to add those time and display it in another text box. I need it in HH:MM format. I don't want seconds as my time picker textbox shows only HH:MM which is enough for me.
I tried many methods to add but i'm not getting the exact time value.
Below is my HTML code
<input type="date" id="opening_date">
<input type="date" id="closing_date">
<input type="time" class="time" id="garage_out_time">
<input type="time" class="time" id="garage_in_time">
<input type="text" id="total_hours">
Below is my script code
$(document).ready(function () {
function ConvertDateFormat(d, t) {
var dt = d.val().split('/');
return dt[0] + '/' + dt[1] + '/' + dt[2] + ' ' + t.val();
}
$(".time").change(function () {
var start = new Date(ConvertDateFormat($('#opening_date'), $('#garage_out_time')));
var end = new Date(ConvertDateFormat($('#closing_date'), $('#garage_in_time')));
console.log(start, end);
var diff = new Date(end - start);
var days = Math.floor(diff / 1000 / 60 / 60 / 24);
var hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / 1000 / 60 / 60);
var total = (days * 24) + hours;
var startTime = document.getElementById("garage_out_time").value;
var endTime = document.getElementById("garage_in_time").value;
var s = startTime.split(':');
var e = endTime.split(':');
var endtime = parseInt(e[1], 10);
var starttime = parseInt(s[1], 10);
var min = endtime + starttime;
var minutes = min ;
var minhours = Math.floor(minutes / 60);
minutes = minutes % 60;
total = total + minhours;
if(minutes > 9){
$("#total_hours").val(total+":"+ minutes);
} else {
$("#total_hours").val(total+":0"+ minutes);
}
});
});
Above code is working for some extent BUT for example when I select 8:12 AM to 8:12 PM , the result I'm getting is 12:32 where answer should be 12:00.
I think you are over-complicating things somewhat. Your ConvertDateFormat() function already gives you what you need, so why are you parsing the time again? Try the code below (with thanks to this this answer)
var start = new Date(ConvertDateFormat($('#opening_date'), $('#garage_out_time')));
var end = new Date(ConvertDateFormat($('#closing_date'), $('#garage_in_time')));
console.log(start, end);
var diff = new Date(end - start);
var mins = Math.floor( diff / 60000 % 60 );
var hours = Math.floor( diff / 3600000 % 24 );
var days = Math.floor( diff / 86400000 );
console.log('days='+days+' hrs='+hours+' mins='+mins);
var totalHours = (days * 24) + hours;
var minsStr = (mins < 10) ? '0' + mins : mins;
$('#total_hours').val(totalHours + ':' + minsStr);
I'm new in javascript.
My PHP script returns a value in this format
d:h:m:s
Now I would like to have a countdown which is able to countdown each second from this.
I modified a countdown. This works once a time, after the countdown "ticks" each second it returns NaN all the time. Any idea what I do wrong?
$(document).ready(function() {
setInterval(function() {
$('.countdown').each(function() {
var time = $(this).data("time").split(':');
var timestamp = time[0] * 86400 + time[1] * 3600 + time[2] * 60 + time[3] * 1;
var days = Math.floor(timestamp / 86400);
console.log(time,timestamp);
var hours = Math.floor((timestamp - days * 86400) / 3600);
var minutes = Math.floor((timestamp - hours * 3600) / 60);
var seconds = timestamp - ((days * 86400) + (hours * 3600) + (minutes * 60))-1;
$(this).data("time",""+days+":"+hours+":"+minutes+":"+seconds);
if (hours < 10) {
hours = '0' + hours;
}
if (minutes < 10) {
minutes = '0' + minutes;
}
if (seconds < 10) {
seconds = '0' + seconds;
}
$(this).text(days + ':' + hours + ':' + minutes + ':' + seconds);
});
}, 1000);
})
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1 class="countdown">02:03:05:59</h1>
As far as I can see you have 2 problems here:
after the first execution you change the pattern of the text you display in the h1. First you have 02:03:05:59. Then you want to write 02 days 03:05:58 into the tag. Next time you parse it, you get the error because you split at : and that does not work anymore as you have days instead of : as the seperator for the first part.
When calculating the minutes, you should also substract the days and not just the hours.
When you wan to keep the dd:hh:mm:ss format, you could do it like this:
$(document).ready(function() {
setInterval(function() {
$('.countdown').each(function() {
var time = $(this).text().split(':');
var timestamp = time[0] * 86400 + time[1] * 3600 + time[2] * 60 + time[3] * 1;
timestamp -= timestamp > 0;
var days = Math.floor(timestamp / 86400);
console.log(days);
var hours = Math.floor((timestamp - days * 86400) / 3600);
var minutes = Math.floor((timestamp - days * 86400 - hours * 3600) / 60);
var seconds = timestamp - days * 86400 - hours * 3600 - minutes * 60;
if (days < 10) {
days = '0' + days;
}
if (hours < 10) {
hours = '0' + hours;
}
if (minutes < 10) {
minutes = '0' + minutes;
}
if (seconds < 10) {
seconds = '0' + seconds;
}
$(this).text(days + ':' + hours + ':' + minutes + ':' + seconds);
});
}, 1000);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1 class="countdown">02:03:05:59</h1>
Your snippet goes from dd:hh:mm:ss to dd days, hh hours. So second time around, your tag contains non-parsable text.
I have changed it to something more precise. Something even MORE precise would be to give a timestamp in milliseconds in the future instead of something with seconds since it will take several seconds to render the page. If you round on minutes from the server, it would likely be better.
var aDay = 24*60*60*1000, anHour = 60*60*1000, aMin = 60*1000, aSec = 1000;
$(document).ready(function() {
$('.countdown').each(function() {
var time = $(this).data("time").split(':');
var date = new Date();
date.setDate(date.getDate()+parseInt(time[0],10))
date.setHours(date.getHours()+parseInt(time[1],10),date.getMinutes()+parseInt(time[2],10),date.getSeconds()+parseInt(time[3],10),0)
$(this).data("when",date.getTime());
});
setInterval(function() {
$('.countdown').each(function() {
var diff = new Date(+$(this).data("when"))-new Date().getTime();
var seconds, minutes, hours, days, x = diff / 1000;
seconds = Math.floor(x%60); x=(x/60|0); minutes = x % 60; x= (x/60|0); hours = x % 24; x=(x/24|0); days = x;
$(this).text(
days + ' day' +(days==1?", ":"s, ") +
hours + ' hour' +(hours==1?", ":"s, ") +
minutes + ' minute'+(minutes==1?", ":"s, ") +
seconds + ' second'+(seconds==1?".":"s.")
);
});
}, 500);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h1 class="countdown" data-time="02:03:05:59"></h1>
I need to get time difference in this format: "HH:MM:SS" using a Javascript.
I have tried this:
var diff = Date.parse( time2) - Date.parse( time1 );
var total_time = (diff / 1000 / 60 / 60) + ":" + (diff / 1000 / 60) + ":" + (diff / 1000);
and this:
var diff = new Date( time2) - new Date( time1 );
var total_time = (diff / 1000 / 60 / 60) + ":" + (diff / 1000 / 60) + ":" + (diff / 1000);
These are the values of time2 and time1:
time1: "2012-11-07 15:20:32.161"
time2: "2012-11-07 17:55:41.451"
And result I am getting in both cases is:
total_time= 0.5250819444444444:31.504916666666666:1890.295
Which you can see is not correct
I think you are getting wrong diff value because of the millisecond part in the date delimited by .. Its not being accepted correctly by the data parser.
Try using the date and time part excluding the milliseconds as below:
var diff = Date.parse(time2.split(".")[0]) - Date.parse( time1.split(".")[0]);
Also while you are getting wrong difference diff, your time computation is also wrong.
It should be:
var second = Math.floor(diff /1000);
//convert the seconds into minutes and remainder is updated seconds value
var minute = Math.floor(second /60);
second = second % 60;
//convert the minutes into hours and remainder is updated minutes value
var hour = Math.floor(minute/60);
minute = minute %60;
var total_time= hour+":" minute+":"+second;
You forgot to remove the number of milliseconds you already calculated from diff. Here is a very verbose example on how you do it in a propper way.
var time1 = "2012-11-07 15:20:32.161",
time2 = "2012-11-07 17:55:41.451",
SECOND = 1000,
MINUTE = SECOND* 60,
HOUR = MINUTE* 60;
var diff = new Date(time2) - new Date(time1);
var hours = Math.floor(diff / HOUR); // Calculate how many times a full hour fits into diff
diff = diff - (hours * HOUR); // Remove hours from difference, we already caluclated those
var minutes = Math.floor(diff / MINUTE); // Calculate how many times a full minute fits into diff
diff = diff - (minutes * MINUTE); // Remove minutes from difference
var seconds = Math.floor(diff / SECOND); // As before
diff = diff - (seconds * SECOND);
var rest = diff;
var total_time = hours + ":" + minutes + ":" + seconds + " " + rest ;
DEMO