Why won't my timer reset every three days dynamically? - javascript

I'd like to know what I'm doing wrong in the logic of my code where I'm trying to make the timer reset every three days. In the code below, I have the timer set to expire September 1, 2019, which's three days from now.
I want it to reset on its own to September 4, 2019, then September 7, 2019, etc.
What am I doing wrong & how can I rectify this? A JSFiddle's also provided below.
https://jsfiddle.net/des6gjqa/
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
p {
text-align: center;
font-size: 60px;
margin-top: 0;
}
</style>
</head>
<body>
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("Sep 1, 2019 9:45:00").getTime();
while(countDownDate.valueOf() < Date.now()) {
countDownDate = new Date(countDownDate.valueOf() + (3 * 24 * 60 * 1000)); // add 3 days to the start date
}
// 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);
// 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";
}
if(countDownDate.valueOf() <= Date.now()) {
countDownDate = new Date(countDownDate.valueOf() + (3 * 24 * 60 * 1000));
}
}, 1000);
</script>
</body>
</html>

Your issue is less complex than what you are thinking. Consider the following:
JavaScript is a client side language (for this example)
The browser data (localStorage, cache, etc) can be easily manipulated.
JavaScript execution stops when the page is closed.
So, the only way to reset the timer every three days with what you are trying is to not close the window during three days. Because when you close it and visit the site once again, the timer will start from 0.
What should you do?
The best approach to this is to have something running on a server. (i.E. PHP, Node.js, Python, Java, etc)
And then, you should use a method to identify the user's machine like the IP address, a custom token (generated server side), etc.
This way, you could assign a cookie to the user visiting your site with a session ID and save in a database the starting date. By doing this, you can easily compare anytime the actual date with the start date anytime and then eval if the lapse is bigger than 3 days, show EXPIRED.
Because otherwise, the script you provided will start counting 3 days every time it is loaded.

See k3llydev's answer for a more robust fix. If you wish for this code to be client side with the assumption that the webpage will be open for the entire duration, here I have made modifications to your jsfiddle: https://jsfiddle.net/as57fjuL/.
Essentially, it is just resetting the 'x' interval after clearing the interval and setting the date again. For simplicity, I have manually set the timeout to about 3 seconds (which can be changed by removing the line countDownDate = new Date(Date.now().valueOf() + 5000);).

You miss second in your expression:
instead of (3 * 24 * 60 * 1000) you should use (3 * 24 * 60 * 60 * 1000)

Related

Django python + javascript countdown – different times in Python and Javascript?

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.

Countdown timer in Google Sheets

I've searched other questions and google/YouTube, and from what I've found, it seems that this is possible, but I have not found this exact use case as an example to pull from. And to preface, I have a slight working knowledge of coding, but not a whole lot.
Here's what I'm trying to accomplish: I want to create a countdown timer in Google Sheets with 2 possible functions (depending on the use case):
1) where I can put in the end date the timer counts down to, either in a specific cell or in the code itself.
2) using a dynamic date (i.e., 30 days from the date the timer was created)
So where I have gotten stuck... I tried using script.google.com and pasted this script for a countdown timer that I found online:
<!-- Display the countdown timer in an element -->
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("Jan 5, 2021 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, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
</script>
But when I run the code, I get "Syntax error. (line 7, file "countdown")".
What modifications do I need to make to the code to get it to work? Or am I using an overcomplicated code to create the timer, and there is a much easier way?
Did you save it as HTML? Or as JS?
Because you should save it as .html since your Javascript is within tags instead of it being a separate file.
The code you pulled from w3schools is just a snippet, I've added and tags and it works just fine.
In your example snippet you also pasted it into the Javascript box instead of the HTML box.
Try this example, it's exactly the code you had!
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
p {
text-align: center;
font-size: 60px;
margin-top: 0px;
}
</style>
</head>
<body>
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("Jan 5, 2021 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);
// 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>
</body>
Another way of doing it is to actually separate your javascript and html into separate files to keep it cleaner and to keep scripts and HTML separated. For example name your HTML index.html and your script timer.js
Then in your HTML, instead of the big blob of script, you simply do
<script src="/timer.js"></script>
// Save this as for example timer.js
// Set the date we're counting down to
var countDownDate = new Date("Jan 5, 2021 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);
// 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);
<!-- Save this as index.html -->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
p {
text-align: center;
font-size: 60px;
margin-top: 0px;
}
</style>
</head>
<body>
<p id="demo"></p>
<!-- Load the Javascript from a separate file called timer.js -->
<script src="/timer.js"></script>
</body>

create countdown based on server hour

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();

How can I change the text colour in this script?

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

Memory Leak with setInterval

I'm currently having an issue with what in belive is a memory leak on a custom PHP website that utilises JS SetInterval
My site loads values from an external PHP file every 30 seconds and appends them to a HTML object, a <p> tag in this case.
<script>
$(window).on('load', function() {
setInterval (function foo1(){
$.get("scriptref.php", function( data ) { //receiving the echo from the php data file
$("#ref").html(data); //putting the echoed value directly into the p tag
});
return foo1;
}(), 30000)});
</script>
I also have a countdown timer that counts downwards in seconds to a specified value.
<script>
var timer = document.getElementById("demo");
var snd = new Audio("/assets/audio/horn.wav"); // buffers automatically when created
// Update the count down every 1 second
var x = setInterval(function() {
var jsnextbreach = document.querySelector("#test").innerHTML;
// Set the date we're counting down to
var countDownDate = new Date(jsnextbreach).getTime();
// 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("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
document.getElementById("demo").innerHTML = "BREACHED";
}
// If the count down is less than an hour replace demo class to warning.
if (distance < 3600000 ) {
timer.className = "warning" ;
}
if (distance > 3600001 ) {
timer.className = "normal" ;
}
if (distance < 3600000 && distance > 3598000) {
snd.play();
}
},1000);
</script>
My problem is that after the page is displayed for an hour or so i get the "Aw snap, google chrome ran out of memory while trying to display this webpage" error. Looking at the profiler I can see that memory usage increases slowly, however I have no idea where to start looking to find out what is causing this leak.
If anyone is able to advise anything that may be wrong with my code or alternatively how i can start troubleshooting what specific element is causing the leak i would be truly grateful!

Categories