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.
Related
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´m facing a need of creating a coundown to display when ever a certain promo will be over, all i have is front-end access via google tag manager, first i manage to get the server hour with js, now i need to set the countdown hour based on the server hour and not local hour.
<script>
// it´s giving the correct hour
var getserver = new Date();
getserver.setHours(getserver.getHours());
var newtets = getserver.toUTCString();
alert(newtets);
// using a basic countdown
var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
/*
var now = new Date();
now.setHours(now.getHours());
var newnow = now.toUTCString();
i tried to replace now with newnow but is not working, how can i transform this
*/
// Find the distance between now an 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);
// 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>
var now = new Date().getTime(); is what getting the time and use it to countdown, this is taking local time, how can i get var now = new Date().getTime(); to be server hour, which i obtained with the 1 script
The only way to get your updated server hour is using an ajax call.
The problem is that the request to the server is not immediate so you will have a delay.
Maybe it would be better to get the user timezone and calculate the promo ending with this information.
You can get the user timezone offset using:
var offset = new Date().getTimezoneOffset();
My system time is UTC + 0 as I am in the UK.
My Script:
<script>
// Set the date we're counting down to
var countDownDate = new Date("<?php echo $date ?>").getTime();
// 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 an 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);
// Output the result in an element with id="demo"
document.getElementById("time").innerHTML = minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("time").innerHTML = "EXPIRED";
window.location.href = "/error";
}
}, 1000);
</script>
My PHP will echo a date + 15 minutes gotten from the serverside, a users order will expire after 15 minutes you see.
So here is a date that the countdown timer would use (2017-11-23 22:50:18) this would be 15 minutes from now, but is UTC + 0 time.
If the users system time was in another country or behind then it would expire and go to the error page straight away.
How would I convert this time to the users timezone (And even if they refresh the page the timer would still be counting down)
The PHP var for $date is gotten from the database and is laid out like so: "2017-11-23 22:50:18"
How do I convert this to the system time of the user?
I hope you understand me, thanks very much! :)
I would like to change the colour of the text displayed to white, however, I have no idea how to go about this, could anyone be so kind to assist me?
Code:
<!-- Display the countdown timer in an element -->
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("Sep 22, 2017 15:37:25").getTime();
// 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 an 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 + "Days " + hours + "Hours "
+ minutes + "Minutes " + seconds + "Seconds ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
</script>
PS I'm a noob and this code is from W3.
CSS Styles Using JavaScript
Every HTML element that you access via JavaScript has a style object. This object allows you to specify a CSS property and set its value.
document.getElementById("p2").style.color = "blue";
There are some ways to do this but the simpliest one is just setting one CSS inline parameter. Like this:
<p id="demo" style="color: white;"></p>
And that makes the magic. :)
Definitly check this -> https://www.w3schools.com/css/default.asp
I have my countdown function (that works).
// Set the date we're counting down to
var countDownDate = new Date("<?= $stop_datejs ?>");
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date();
// Find the distance between now an 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);
// 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 = "ACTUALIZA LA PÁGINA";
}
}, 1000);
But I need to compare with a php variable $actual_date (server date)
// Get todays date and time
var now = new Date("<?= $actual_date ?>");
That works but stops updating every second. What is the problem?
Thanks
The variable now will not be updated, because the variable will only be written once. So if you load the the webpage the value will be set once but not updated, because the website does not update again (Only your interval).
To provide this you can simply use:
// Get todays date and time
var now = new Date();
This will only use the current time for the new instance of Date. If your <?= $actual_date ?> is not the current timestamp or you want to sync if for all browsers/pc with an incorrect time setting you should have a look at AJAX. Using AJAX is the easiest way to get the updated time from the backend.
jQuery Ajax:
http://api.jquery.com/jquery.ajax/