My JavaScript clock widget crashes Firefox - javascript

I am a JavaScript noob and realise that I need assistance.
All I want is to show a simple real-time clock with the time and AM/PM in separate SPANs.
The issue is that if I keep the tab open for 20-40 minutes (varies depending on how many other tabs I have open), it crashes the tab with an out of memory error. I have only tested this on Firefox (72.0.2) for now.
Why is my code so awfully memory intensive? It usually starts at around 2.4MB and then gradually increases and exceeds 42MB, then drops again, increases again and repeats the cycle several times until the tab crashes.
I've read aboout Garbage Collection but have no idea about how it works or if it's related to this problem.
Note that I've tried swapping setInterval with setTimeout but it's the same result.
This is my JavaScript:
window.onload = function() {
clock();
function clock() {
var now = new Date();
var TwentyFourHour = now.getHours();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var mid = 'PM';
if (min < 10) {
min = "0" + min;
}
if (hour > 12) {
hour = hour - 12;
}
if (hour == 0) {
hour = 12;
}
if (TwentyFourHour < 12) {
mid = 'AM';
}
document.getElementById('time-core').innerHTML = hour + ':' + min;
setInterval(clock, 1000);
document.getElementById('time-suffix').innerHTML = mid;
setInterval(clock, 1000);
}
}
And this is my HTML:
<span class="show-time" id="time-core"></span><span class="show-time-suffix" id="time-suffix"></span>
Thank you!

As Andreas said in his comment:
Every call of clock() adds two new intervals that each will call clock(). So after the first round we then have two scheduled clock() calls, then 4, then 8, then ...
One way to solve that would be to remove the setInterval from inside the clock function, like the example below.
window.onload = function() {
clock(); // Run it first so we don't have to wait 1 second
setInterval(clock, 1000); // Updates the clock every second
function clock() {
var now = new Date();
var TwentyFourHour = now.getHours();
var hour = now.getHours();
var min = now.getMinutes();
var sec = now.getSeconds();
var mid = 'PM';
if (min < 10) {
min = "0" + min;
}
if (hour > 12) {
hour = hour - 12;
}
if (hour == 0) {
hour = 12;
}
if (TwentyFourHour < 12) {
mid = 'AM';
}
document.getElementById('time-core').innerHTML = hour + ':' + min;
document.getElementById('time-suffix').innerHTML = mid;
}
}

Related

Why does EST JavaScript Date sets 12:00:00AM to 0:00:00 AM?

my JavaScript display time function works fine, but once it hits 12:00:00 AM EST, it changes to 0:00:00 AM. Essentially, I want it to show as 12:00:00 AM when the clock strikes midnight. I have included my code below so anyone can help? Thank you!
let session = document.getElementById("session");
if (session) {
displayTime();
setInterval(displayTime, 1000);
clearInterval(displayTime);
}
function displayTime() {
let dateTime = new Date();
let hrs = dateTime.getHours();
let mins = dateTime.getMinutes();
let sec = dateTime.getSeconds();
if (hrs > 12) {
session.innerHTML = "\xa0" + "PM";
} else {
session.innerHTML = "\xa0" + "AM";
}
if (hrs > 12) {
hrs = hrs - 12;
}
if (mins < 10) {
mins = "0" + mins;
}
if (sec < 10) {
sec = "0" + sec;
}
document.getElementById("hours").innerHTML = hrs;
document.getElementById("minutes").innerHTML = mins;
document.getElementById("seconds").innerHTML = sec;
}
There are two things to change.
The condition to display "PM" should be >= 12 instead of > 12
The mapping of 24-hours to 12-hours should never leave 0 as-is. You can use the remainder operator.
Here are the corrected relevant lines:
if (hrs >= 12) {
session.innerHTML = "\xa0" + "PM";
} else {
session.innerHTML = "\xa0" + "AM";
}
hrs = (hrs + 11) % 12 + 1;
Alternative
To format a time, look at toLocaleTimeString with its options:
dateTime.toLocaleTimeString("en-US")
If you really need to chop the date parts into different elements on your HTML document, then:
function displayTime() {
let dateTime = new Date();
let [hrs, mins, sec, apm] = dateTime.toLocaleTimeString("en-US").split(/\W/);
console.log(hrs, mins, sec, apm);
document.getElementById("hours").textContent = hrs;
document.getElementById("minutes").textContent = mins;
document.getElementById("seconds").textContent = sec;
document.getElementById("session").textContent = "\xa0" + apm;
}
Remarks
Unrelated, but clearInterval is called at the wrong time and with the wrong argument, which luckily makes it ineffective, or your timer wouldn't tick at all.
clearInterval should get as argument a value that was returned by a previous call to setInterval.
In your code clearInterval is executed immediately after setInterval, which makes little sense. You should call it conditionally in the callback that is passed to setInterval. Maybe when a certain time has passed...

Timer not working when using readline-sync (Javascript)

I am making a game that keeps track of the time you take to complete the game, however i realised that the timer does not continue when i am asking for input.I tried to wait 10 seconds before typing a input but after i input a value the time is 00:00.Must i create a separate file for the timer or is there a possible way for the timer to run.Please help thanks!
var readline = require('readline-sync');
seconds = 0;
minute = 0;
timer = setInterval(() => {
if (seconds == 60) {
seconds = 0;
minute++;
}
seconds++;
}, 1000);
var input = readline.question('Input:');
clearInterval(timer);
//String to show time
if (minute < 10 && seconds < 10)
time = '0' + minute + ':0' + seconds;
else if (minute < 10 && seconds >= 10)
time = '0' + minute + ':' + seconds;
else if (minute >= 10 && seconds < 10)
time = minute + ':0' + seconds;
else
time = minute + ':' + seconds;
console.log(time);
It is easier just to create a Date object with new Date() and substract it from another Date created after the user Input.
var dateStart = new Date();
var input = readline.question('Input:');
var difference = new Date() - dateStart(); // time elapsed in milliseconds
For more complex cases I'd recommend looking up the libraries moment.js or date-fns.

Bugging getDate function

Why my getDate function is bugging sometimes and Im getting double response in console?
https://imgur.com/a/sxk0tbC
here's my code
function getDate() {
var newDate = new Date();
var year = newDate.getFullYear();
var month = newDate.getMonth()+1;
var day = newDate.getDate();
var hours = newDate.getHours();
var minutes = newDate.getMinutes();
var seconds = newDate.getSeconds();
if (month < 10) {
month = "0"+month;
}
if (day < 10) {
day = "0"+day;
}
if (hours < 10) {
hours = "0"+hours;
}
if (minutes < 10) {
minutes = "0"+minutes;
}
if (seconds < 10) {
seconds = "0"+seconds;
}
return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds;
}
setInterval(function() {
console.log(getDate())
},1000)
Several reasons. The setInterval function doesn't always run exactly 1000 milliseconds later; after all, no clock is perfect. Also, in between each 1000 millisecond wait, the execution time of the program must be taken into account, which is probably a couple of milliseconds. As for duplicate times, if the wait is slightly less than a second, or the JavaScript date has a slight latency after the actual computer time, then duplicates can occur. The bottom line is though that on average, it will execute every 1000 milliseconds, plus the execution time of the actual function.

How do I pull javascript time other than from the user's device

I use a script that coverts Earth Time into an in-game time for a game (Eorzea Time). The script that was originally written is here.
My issue is that this pulls the Earth Time from the user's device clock. So if the clock is not correct on their device the conversion to Eorzea time is not accurate.
I'd like to pull Earth Time from a clock that is guaranteed to be accurate. I've been unable to figure out how to do this.
As an example. If you view this script alongside this site (www.ffxivclock.com) and change your time by even a minute or two...the jsfiddle clock will be off while the ffxivclock.com time will still be correct.
var E_TIME = 20.5714285714;
var global = {
utcTime: null,
eorzeaTime: null
};
window.setInterval(updateClock, Math.floor(1000 * 60 / E_TIME));
function updateClock() {
global.utcTime = new Date().getTime();
var eo_timestamp = Math.floor(global.utcTime * E_TIME);
global.eorzeaTime = new Date();
global.eorzeaTime.setTime(eo_timestamp);
showTime();
}
function showTime() {
var d = new Date();
d.setTime(global.eorzeaTime);
var eTime = document.getElementById('e-time');
var hours = d.getUTCHours();
var ampm = hours > 11 ? "PM" : "AM";
if(hours > 12)
hours -= 12;
hours = padLeft(hours);
var minutes = d.getUTCMinutes();
minutes = padLeft(minutes);
eTime.innerHTML = hours + ":" + minutes + " " + ampm;
}
function padLeft(val){
var str = "" + val;
var pad = "00";
return pad.substring(0, pad.length - str.length) + str;
}
updateClock();

Javascript countdown timer can't set half past hour

I'm trying to use a countdown timer to count to a certain time everyday (monday to friday). So far everything works, except it can only be set to count to a certain hour (based on the 24 hour clock) without a half hour included. So for example, if I wanted to count to 4PM, I'd set var target = 16; but if I wanted 4:30 and I tried to set var target = 1630; it doesn't work. Unfortunately I don't have much experience with javascript, but I believe the problem is either with the way it's evaluating the target time using the getHours function but not sure where to take it from there.
if (document.getElementById('countdownTimer')) {
pad = function(n, len) { // leading 0's
var s = n.toString();
return (new Array( (len - s.length + 1) ).join('0')) + s;
};
function countDown() {
var now = new Date();
if ( (now.getDay() >= 1) && (now.getDay() <= 5) ) { // Monday to Friday only
var target = 15; // 15:00hrs is the cut-off point
if (now.getHours() < target) { // don't do anything if we're past the cut-off point
var hrs = (target - 1) - now.getHours();
if (hrs < 0) hrs = 0;
var mins = 59 - now.getMinutes();
if (mins < 0) mins = 0;
var secs = 59 - now.getSeconds();
if (secs < 0) secs = 0;
var str = pad(hrs, 2) + ':' + pad(mins, 2) + '.<small>' + pad(secs, 2) + '</small>';
document.getElementById('countdownTimer').innerHTML = str;
}
}
}
var timerRunning = setInterval('countDown()', 1000);
}
If you're ok with considering another method, the following javascript will count down (in seconds) to any date in the future (and count up after the date has passed).
// new Date(year, month, day, hours, minutes, seconds, milliseconds)
var target = new Date(2014, 0, 30, 12, 30, 0, 0)
function countdown(id, targetDate){
var today = new Date()
targetDate.setDate(today.getDate())
targetDate.setFullYear(today.getFullYear())
targetDate.setMonth(today.getMonth())
var diffMillis = targetDate - today
if (diffMillis >= 0){
document.getElementById(id).innerHTML = millisToString(diffMillis)
}
}
setInterval(function(){countdown('seconds', target)},1000)
It uses the javascript date object, so you can literally use any date.
Updated example to do:
format the countdown using hours:minutes:seconds etc
stop the timer after the date is reached
Updated: updated code to override the targetDate to today's date.
Example: http://jsfiddle.net/kKx7h/5/
For 4:30PM, try var target = 16.5 instead of var target = 1630;
You now need to add another variable for the minutes. We can have target as an object literal rather than declare two variables for time:
var target={hour: 15, minute:30};
if ( (now.getHours() < target.hour) && () now.getMinutes() < target.minute ){

Categories

Resources