Common headache, but each answer seems to be unique, I have some simple JS counting down until december 15th, this countdown works on each browser except I get 'NaN' for each day, hour, minute on safari.
<p id="clockdiv" class="decofont ">
<span class="days"></span>
<span class="hours"></span>
<span class="minutes"></span></p>
<!--302 D | 21 H | 48 M december 15 2017 -->
var deadline = '12 15 2017';
function getTimeRemaining() {
var t = Date.parse('12 15 2017') - 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));
var time = {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
var output_time = document.getElementById('clockdiv');
output_time.innerHTML = days + ' D | ' + hours + ' H | ' + minutes + ' M';
setTimeout(getTimeRemaining, 60000);
}
getTimeRemaining(deadline);
Bonus points if you have a link to JS cross browser compatibility (common functions that don't work on all browsers). What is causing this to break on safari and what is the most simple alternative?
The root of your issue is that you are parsing a string and expecting all browsers to parse it the same. Parsing of date string is almost entirely implementation dependent, there is only one format (ISO 8601 extended) that ECMA-262 requires to be supported.
So in the line:
var t = Date.parse('12 15 2017') - Date.parse(new Date());
you should use the Date constructor. Also, you should not use Date.parse(new Date()), just use new Date or Date.now() so:
var t = new Date(2017,11,15) - new Date();
which will return the difference in milliseconds between the two dates:
console.log(new Date(2017,11,15) - new Date());
Also see Difference between dates in JavaScript.
Related
I am getting the elapsed time in minutes, hours and days, between two dates, a past date and the current one, I already get this data, but I want this data to change as the minutes, days and hours increase. For example, when I get to 60 minutes, the time changes to 1 hour and the minutes go to 0, when 24 hours go by, these hours change to a day and the hours go back to 0, and so on, the data I get keeps increasing , how can I do this?
const calculateDate = () => {
const date = new Date('Sun Sep 01 2022 01:32:06 GMT-0500');
const currentDate = new Date();
const minutes= Math.floor((currentDate.getTime() - date.getTime()) / 1000 / 60);
const hours= Math.floor((currentDate.getTime() - date.getTime()) / 1000 / (3600));
const days= Math.floor((currentDate.getTime() - date.getTime()) / (1000*60*60*24));
}
With this, get the minutes, hours and days, but how would you update so that when you reach 60 minutes it goes to one hour and 24 hours to one day?
The JavaScript Date object has built in functions for what you want to do.
var now = new Date()
var h = now.getHours()
var m = now.getMinutes()
var s = now.getSeconds()
The new Date created in above example is set to the time it was created.
You can get the current time using the Date object itself:
var current = Date()
With your method you always see the full duration just in a different unit.
You have to use the modulo operator to get only the "missing part" (the remainder of the division) to the next unit:
const date = new Date('Sun Sep 01 2022 01:32:06 GMT-0500');
const currentDate = new Date();
const dateDiff = (currentDate.getTime() - date.getTime()) / 1000;
const seconds = Math.floor(dateDiff) % 60;
const minutes = Math.floor(dateDiff / 60) % 60;
const hours = Math.floor(dateDiff / (60 * 60)) % 24;
const days = Math.floor(dateDiff / (60 * 60 * 24));
I'm using date-fns. I need to create a countdown to the next 10th of the month.
For example, if today is 5th Feb, then the countdown should be to 10th Feb. If today is say 15th Feb, then it should count to 10th March, and so on.
How can I do this with date-fns or even with plain javascript?
You must first find the target date, like this one:
const today = startOfToday();
let target = setDate(today, 10);
if (isBefore(target, today)) {
target = addMonths(target, 1);
}
Then calculate time remaining until the target:
const diff = differenceInSeconds(target, new Date());
const days = Math.floor(diff / 86400);
const hours = Math.floor((diff - days * 86400) / 3600);
const minutes = Math.floor((diff - days * 86400 - hours * 3600) / 60);
const seconds = diff - days * 86400 - hours * 3600 - minutes * 60;
Use days, hours, minutes, seconds for create a countdown. Don't forget to import required functions from date-fns.
EDIT #2
Again, I spend some time with the code and some more research:
In my views.py I do the following
timestamp = datetime.combine(inst.date, inst.time).strftime('%s')
timestamp get passed through the template to javascript.
But the unexplainable (for me) happens in the views.py
Output views.py
Timestamp: 2022-02-03 20:10:00
Timestamp.strftime('%s'): 1643919000
Output javscript
Date Thu Feb 03 2022 21:10:00 GMT+0100 (Central European Standard Time)
1643919000000
The (milli-)seconds outputs are basically the same but the datetime.datetime object in Python and the Date object in Javascript is different.
What magic is at play here?
EDIT
After some re-tuning (thanks to Kyvex in the comments), I got the gap down to one hour. Which is now somehow explainable:
This is the .js code now:
var countDownDate = JSON.parse(document.getElementById('timestamp').textContent); //new Date("Feb 2, 2022 22:59:00 GMT+0000").getTime();
var x = setInterval(function () {
var now = new Date().getTime();
console.log(countDownDate);
const GMT = 3600000;
console.log(now);
var difference = countDownDate * 1000 - now - GMT;
var days = Math.floor(difference / (1000 * 60 * 60 * 24));
var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((difference % (1000 * 60)) / 1000);
document.getElementById("clock").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
if (difference < 0) {
clearInterval(x);
document.getElementById("clock").innerHTML = "<h1>EXPIRED!</h1>";
}
}, 1000);
I logged both countDownDate and now. It seems like they use different offsets. countDownDate, coming from python, seems to have an offset of GMT+0000, whereas now returns a GMT+0100. I now hard-coded this difference by subtracting const GMT = 3600000. But this cannot be the solution to the problem.
How can I get them in sync?
I am relatively new and just a hobbyist programmer. At the moment I try to work on a small Django project where I want to set a date and time in the future via a form and after the user clicks "Submit", the page shows a countdown from now until the set date and time.
After experimenting a bit with the datetime module, I find myself with an awkward problem. I have two fields in the forms: 1. date, and 2. time
With timestamp = datetime.datetime.combine(date, time).strftime('%s') I combine those two information and get a seconds output. I then, pass timestamp to my .js file with {{ timestamp|json_script:'timestamp'}}.
Here is my .HTML code:
<body>
{% load static %}
<html>
<form method="post" enctype="multipart/form-data">
{% csrf_token %} {{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% if inst %}
<center><h3>Success</h3>
<div id="clock"></div></center>
{{ timestamp | json_script:'timestamp'}}
<script src="{% static 'js/timer.js' %}"></script>
{% endif %}
</html>
</body>
If I now set setTime only 2 minutes in the future, my countdown shows 4 hours, and the difference is 3 hours.
I get that there are timezone and DST differences at play but from where I am nothing would add up to 3 or 4 hours.
Excuse me if this is all too unprofessional and just a lay description of my problem. I would appreciate the community's help since I am trying to get better and understand all those underlying processes here.
Thanks a lot!
I just solved it!!
Here is my .js code
var countDownDate = JSON.parse(document.getElementById('timestamp').textContent);
var newDate = new Date(countDownDate * 1000);
// Get NOW
var now = new Date();
// Get Timezone offset from imported date
var tzDifference = newDate.getTimezoneOffset();
// calculate the new offset time
var offsetNewTime = new Date(newDate.getTime() + tzDifference * 60 * 1000)
var x = setInterval(function () {
var now = new Date();
// console.log(now.getTime());
var difference = offsetNewTime - now;
var days = Math.floor(difference / (1000 * 60 * 60 * 24));
var hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((difference % (1000 * 60)) / 1000);
document.getElementById("clock").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
if (difference < 0) {
clearInterval(x);
document.getElementById("clock").innerHTML = "<h1>EXPIRED!</h1>";
}
}, 1000);
With the help from this post: add or subtract timezone difference to javascript Date
Somehow I got two different time offsets from python and javascript. So I used getTimezoneOffset(); to account for that and add this offset to the imported datetime.
This just works now and I hope it does independently of the timezone one finds themselves in.
If you have any comments on that please feel free to add them, of course.
i can image someone had donde this already or it can be considered a duplicated question, i've been searching for weeks and i can't figure out how to accomplish this.
I have a countdown made in js, the problem i'm facing is that when ever i test it in another country the times throw out different hours example.
i'm in centralamerica, end date is apr 16, 2018 23:59:59" if i test this in centralamerica it says 6 days and 10 hours remaining, if i run this in italy for example it says 6 days and 3 hours remaining, i need it to be equal all the time and that the timezone doesn´t affects, is this even possible, and please help on how to get it done.
the script i have is working but not the way i need to, i have a promo that will expire on "apr 16, 2018 23:59:59" so if it only has 5 hours remaining it shout say 5 hours remaining no matter where its been seeing from, but that is not happening.
$("#masterslider").append("<p id='demo'>.</p>")
$("#masterslider").append("<span> remaining time </span>")
//******************************** update date here ************************
var serverDate = new Date("apr 16, 2018 23:59:59");
var offset = serverDate.getTimezoneOffset();
serverDate = addOffset(serverDate, offset);
setInterval(function(){
updateCountdown();
}, 1000);
function addOffset(date, offset) {
var time = date.getTime() ;
return new Date(time + offset * 6000);
}
function updateCountdown() {
var userDate = new Date();
var distance = serverDate.getTime() - userDate.getTime();
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);
if(serverDate.getTime() > userDate.getTime()){
$('#demo').html( days +"day(s)"+ " / " + hours + "hour(s)" + minutes + "minutes(s)");
}
else
{
$("#demo").html(mas);
$("#masterslider span").hide();
}
}
</script>
I've checked and setting correct timezone for "event timestamp" works for me regardless local client timezone I use.
let targetDate = new Date("2018-04-11 23:59:59 GMT-0800");
let refreshDelayMs = 1000;
function updateCounter() {
let distance = (targetDate - new Date()) / 1000;
let seconds = Math.floor(distance % 60).toString().padStart(2, '0');
distance = distance / 60;
let minutes = Math.floor(distance % 60).toString().padStart(2, '0');
distance = distance / 60;
let hours = Math.floor(distance % 24).toString().padStart(2, '0');
let days = Math.floor(distance / 24).toString().padStart(2, '0');
document.querySelector('.counter').innerHTML = `${days} days ${hours}:${minutes}:${seconds}`;
setTimeout(updateCounter, refreshDelayMs);
}
updateCounter();
Remains: <span class="counter"></span>
You can use moment-timezone from CDN or use NPM
repl.it sample
const moment = require("moment-timezone");
function toTimeZone(time, offset) {
var format = 'YYYY/MM/DD HH:mm:ss ZZ';
return moment(time, format).utcOffset(offset).format(format);
}
toTimeZone("2018/04/10 15:37", "+0730")
I have implemented a timer counter with a given starting date. Everything is normal until the point in which I want it to show months/days/minutes/seconds. I see where it lacks logic in my code, so my question is: Is there an elegant way to deal with that (the division of the total seconds), or should I just go with nested endless if statements?
var deadline = "December 18 2016 08:00:00 GMT+0300";
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) % 30 );
var months = Math.floor( t/(1000*60*60*24*30) );
return {
'total': t,
'months': months,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}