SetInterval() within setInterval() at different times - javascript

I would like to ask how is it possible to run a function every 60 seconds which has another timer inside it that only runs every 5 minutes
function systemTime() {
let currentTime = new Date();
let diem = "AM";
let h = currentTime.getHours();
let m = currentTime.getMinutes();
let s = currentTime.getSeconds();
if (h == 0) h = 12;
if (h > 12) diem = "PM";
if (h < 10) h = "0" + h;
if (m < 10) m = "0" + m;
if (s < 10) s = "0" + s;
return {
h: h.toString(),
m: m.toString(),
diem: diem
}
}
async function serverTime() {
let timeUrl = 'https://worldtimeapi.org/api/timezone/Europe';
let response = await fetch(timeUrl);
let data = await response.json();
let timestamp = data.datetime;
let time = timestamp.split('T')[1].split('.')[0];
let timeArray = time.split(':');
if(parseInt(timeArray[0]) > 12) timeArray[2] = 'PM'
else timeArray[2] = 'AM';
return {
h: timeArray[0],
m: timeArray[1],
diem: timeArray[2]
}
}
async function clock() {
let h, m, diem;
let container = document.querySelector('#displayClock');
container.innerHTML = `${h} : ${m}`;
setInterval(() => clock(), 60000);
// I would like to grab the server time every 5 min for comparison
setInterval(() => {}, 60000*5) // set minutes and hours to the server time
}
I would like to call the clock() function every 60s to display the time on a page but at the same time I would like to call the serverTime() function every 5 minutes to compare the values and take the serverTime if they are not the same.
Calling clock() every 60s isn't the problem. setInterval will solve this but if within it I set an Interval of 5 min then every 10 seconds there will be a new 5 min interval set?
Thankyou very much for your help.

You are recursively setting intervals:
async function clock() {
//...
setInterval(() => clock(), 60000);
setInterval(() => {}, 60000*5);
}
So every time you call clock (every minute), you are setting more and more intervals for both clock and, well, an empty function. (It looks like you forgot to try to call serverTime?)
If you want to call clock every 60 seconds, then just set an interval to call it every 60 seconds:
async function clock() {
//...
}
setInterval(clock, 60000);
If you want to call serverTime every 5 minutes, then just set an interval to call it every 5 minutes:
async function serverTime() {
//...
}
setInterval(serverTime, 300000);
There's no need to do this recursively. Doing so means that setting an interval is part of the operation being repeated, which isn't what you want.
Edit: To demonstrate the problem, watch your browser console on this link: https://jsfiddle.net/Laqt4oe5 How many times do you expect the number to increase every 3 seconds? How many times is it actually increasing?

I have used this to solve the issue and obtain what i wanted
/**
* Display a digital clock
*
* #param {string} container - placement of the clock on the page
*/
function systemTime() {
let currentTime = new Date();
let diem = "AM";
let h = currentTime.getHours();
let m = currentTime.getMinutes();
let s = currentTime.getSeconds();
if (h == 0) h = 12;
if (h > 12) diem = "PM";
if (h < 10) h = "0" + h;
if (m < 10) m = "0" + m;
if (s < 10) s = "0" + s;
return {
h: h.toString(),
m: m.toString(),
diem: diem
}
}
/**
* Returns an object containing hours and minutes from the worldTimeAPI
*/
async function serverTime() {
let timeUrl = 'https://worldtimeapi.org/api/timezone/Europe/Berlin';
let response = await fetch(timeUrl);
let data = await response.json();
let timestamp = data.datetime;
let time = timestamp.split('T')[1].split('.')[0];
let timeArray = time.split(':');
if(parseInt(timeArray[0]) > 12) timeArray[2] = 'PM'
else timeArray[2] = 'AM';
console.log('Time fetched from world API');
return {
h: timeArray[0],
m: timeArray[1],
diem: timeArray[2]
}
}
/**
* Fires every 5 min and compares server and system times
*/
async function compareTime() {
let server = await serverTime();
let system = systemTime();
let container = document.querySelector('#displayClock');
if(system.h != server.h || system.m != server.m) container.innerHTML = `${server.h} : ${server.m} ${server.diem}`;
else container.innerHTML = `${system.h} : ${system.m} ${system.diem}`;
setInterval(() => compareTime(), 60000);
}
/**
* Fires every 1 min and displays system time
*/
function displayTime() {
let system = systemTime();
let h = system.h;
let m = system.m;
let diem = system.diem;
let container = document.querySelector('#displayClock');
container.innerHTML = `${h} : ${m} ${diem}`;
setInterval(() => displayTime(), 60000);
}

Related

Countdown Timer Ends Meessage

A few days ago, I created countdown timer by watching a video on YouTube. The countdown timer is completely perfect but one thing is missing from it. When the timer goes to the zero it will hide from the page.
I want to show some text when timer ends. Like if timer goes to zero then timer hides and show this message "You are too late. Stay with us".
This is a .js code in which I need some modification.
const dayDisplay = document.querySelector(".days .number");
const hourDisplay = document.querySelector(".hours .number");
const minuteDisplay = document.querySelector(".minutes .number");
const secondDisplay = document.querySelector(".seconds .number");
const countdownContainer = document.querySelector(".countdown-container");
const endDate = new Date("August 04 2020 10:38:00");
let saleEnded = false;
const updateTimer = () => {
if(countdownContainer) {
let currentDate = new Date();
let difference = endDate.getTime() - currentDate.getTime();
if (difference <= 1000) {
saleEnded = true;
}
const second = 1000;
const minute = second * 60;
const hour = minute * 60;
const day = hour * 24;
let newDay = Math.floor(difference / day);
let newHour = Math.floor((difference % day) / hour);
let newMiute = Math.floor((difference % hour) / minute);
let newSecond = Math.floor((difference % minute) / second);
dayDisplay.innerText = newDay < 10 ? "0" + newDay : newDay;
hourDisplay.innerText = newHour < 10 ? "0" + newHour : newHour;
minuteDisplay.innerText = newMiute < 10 ? "0" + newMiute : newMiute;
secondDisplay.innerText = newSecond < 10 ? "0" + newSecond : newSecond;
};
};
setInterval(() => {
if (!saleEnded) {
updateTimer();
} else {
countdownContainer.style.display = "block";
}
}, 1000);
Try this?
setInterval(() => {
if (!saleEnded) {
updateTimer();
} else {
countdownContainer.style.display = "block";
countdownContainer.innetHTML="You are too late. Stay with us";
}
}, 1000);

Difference between dates erroneously calculating getHours?

I am writing a function that will help me log elapsed times between my code blocks.
function getTimestamp(date) {
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
return `${(hours < 10 ? '0' + hours : hours)}-${(minutes < 10 ? '0' + minutes : minutes)}-${(seconds < 10 ? '0' + seconds : seconds)}`;
}
//example (wait 3 secs to see the output)
(async function(){
let d1 = new Date();
let seconds = 3;
let interval = setInterval(function(){
//console.clear();
console.log(`wait ${seconds--} seconds...`);
}, 1000);
let waitPromise = new Promise((ok,err) => {
setTimeout(function(){
ok(new Date());
}, seconds * 1000);
});
let d2 = await waitPromise;
//console.clear();
clearInterval(interval);
console.log(`Elapsed time: ${getTimestamp(new Date(d2 - d1))}`)
})();
I don't understand why my date differences are always showing 2 hours. The seconds and minutes are showing correctly, but I get a constant "2" hours together. Why is that happening ?
First of all, never use Date for time intervals. It will cause problems. Second, you should use performance.now() because it's meant for performance analysis and provides extra precision.
function getHumanReadableTime(t) {
const hours = Math.floor(t / 3600000),
minutes = Math.floor(t / 60000) % 60,
seconds = Math.floor(t / 1000) % 60;
return `${hours}-${minutes}-${seconds}`
}
(async () => {
const initialTimestamp = performance.now();
await new Promise( ok => {setTimeout(ok, 3000)});
const finalTimestamp = performance.now();
alert(getHumanReadableTime(finalTimestamp - initialTimestamp));
})()

How to make a countdown timer counting down in specific set of seconds?

I have the following code:
var hours = Math.floor((timeLeft) / 3600);
var minutes = Math.floor((timeLeft - (hours * 3600)) / 60);
var seconds = Math.floor((timeLeft - (hours * 3600) - (minutes * 60)));
if (hours < "10") {
hours = "0" + hours;
}
if (minutes < "10") {
minutes = "0" + minutes;
}
if (seconds < "10") {
seconds = "0" + seconds;
}
$("#" + divName).html(hours + ":" + minutes + ":" + seconds);
Let Suppose these Values.
End date = 13 Feb 2018
Now Date = 12 Feb 2018
23:59:59 Current Counter
And its Works like
23:59:58
23:59:57
Now I want to show Counter like this on Every Second I want to Decrements 2 or 3 Seconds depending upon my Requirement
23:59:59
23:59:57
23:59:55
How can I do that?
Neither setTimeout nor setInterval is accurate and therefore reliable. So instead of accumulating errors on each iteration I prefer to solve this independant of any interval, only using Date.now()
A simple version would be:
//a simple linear equation over time, independant of any interval
function clock(startValue=Date.now(), speed=1){
let m=+speed||0, b=(+startValue||0)-m*Date.now();
//every time you call this function, it will give you
//the value for the very moment you call this function
//wether you do this every second, every hour of on every frame
return function time(){
let value = m*Date.now()+b, v = Math.abs(value);
return {
value,
sign: value < 0? "-": "",
ms: Math.floor(value)%1e3,
seconds: Math.floor(v/1e3)%60,
minutes: Math.floor(v/6e4)%60,
hours: Math.floor(v/36e5)%24,
days: Math.floor(v/864e5)
}
}
}
//I find these constants pretty handy when describing time
const MS=1,SECOND=1e3,SECONDS=SECOND,MINUTE=6e4,MINUTES=MINUTE,HOUR=36e5,HOURS=HOUR,DAY=864e5,DAYS=DAY,WEEK=6048e5,WEEKS=WEEK;
//this is more descriptive
let countDown = clock(24*HOURS, -10*SECONDS / SECOND);
//than this
//let countDown = clock(86400000, -10);
let output = document.querySelector('#time');
//a helper
const leadingZero = v => String(v).padStart(2,0);
//this is just rendering the current time
//it has nothing to do with computing the time
setInterval(function(){
let { sign, hours, minutes, seconds } = countDown();
let hms = [hours, minutes, seconds].map(leadingZero).join(":");
output.textContent = sign + hms;
}, 100);
<div id="time"></div>
But usually I'd use a more complete/versatile implementation
class Clock {
constructor(value=Date.now(), speed=1){
this.m = +speed || 0;
this.b = +value || 0;
this.p = true;
}
get value(){ return this.p? this.b: this.m*Date.now() + this.b }
set value(arg){
let value = +arg || 0;
this.b = this.p? value: value - Date.now()*this.m;
}
get paused(){ return this.p }
set paused(arg){
let pause = !!arg;
if(pause === this.p) return;
this.b += this.m*Date.now() * (pause? 1: -1);
this.p = pause;
}
get speed(){ return this.m }
set speed(arg){
let speed = +arg || 0;
if(speed === this.m) return;
if(!this.p)
this.b += Date.now() * (this.m-speed);
this.m = speed;
}
valueOf(){ return this.value; }
start(){
this.paused = false;
return this;
}
stop(){
this.paused = true;
return this;
}
time(){
let value = this.value, v = Math.abs(value);
return {
value,
sign: value < 0? "-": "",
ms: Math.floor(value)%1e3,
seconds: Math.floor(v/1e3)%60,
minutes: Math.floor(v/6e4)%60,
hours: Math.floor(v/36e5)%24,
days: Math.floor(v/864e5)
}
}
}
const MS=1,SECOND=1e3,SECONDS=SECOND,MINUTE=6e4,MINUTES=MINUTE,HOUR=36e5,HOURS=HOUR,DAY=864e5,DAYS=DAY,WEEK=6048e5,WEEKS=WEEK;
let speed = this.speed;
let countDown = new Clock(24*HOURS-1, speed.value);
let output = document.querySelector('#time');
this.startBtn.onclick = () => countDown.start();
this.stopBtn.onclick = () => countDown.stop();
speed.onchange = speed.onkeyup = () => {
if(!isNaN(+speed.value)) countDown.speed = speed.value;
}
const leadingZero = v => String(v).padStart(2,0);
//this is just rendering the current time
//it has nothing to do with computing the time
setInterval(function(){
let { sign, hours, minutes, seconds } = countDown.time();
output.textContent = sign + [hours, minutes, seconds].map(leadingZero).join(":");
}, 100);
console.log(countDown);
<div id="time"></div>
<input type="button" id="startBtn" value="start" />
<input type="button" id="stopBtn" value="stop" />
<input type="number" id="speed" value="-2" />
Does this help?

Find elapsed time in javascript

I'm new to JavaScript and I'm trying to write a code which calculates the time elapsed from the time a user logged in to the current time.
Here is my code:-
function markPresent() {
window.markDate = new Date();
$(document).ready(function() {
$("div.absent").toggleClass("present");
});
updateClock();
}
function updateClock() {
var markMinutes = markDate.getMinutes();
var markSeconds = markDate.getSeconds();
var currDate = new Date();
var currMinutes = currDate.getMinutes();
var currSeconds = currDate.getSeconds();
var minutes = currMinutes - markMinutes;
if(minutes < 0) { minutes += 60; }
var seconds = currSeconds - markSeconds;
if(seconds < 0) { seconds += 60; }
if(minutes < 10) { minutes = "0" + minutes; }
if(seconds < 10) { seconds = "0" + seconds; }
var hours = 0;
if(minutes == 59 && seconds == 59) { hours++; }
if(hours < 10) { hours = "0" + hours; }
var timeElapsed = hours+':'+minutes+':'+seconds;
document.getElementById("timer").innerHTML = timeElapsed;
setTimeout(function() {updateClock()}, 1000);
}
The output is correct upto 00:59:59 but after that that O/P is:
00:59:59
01:59:59
01:59:00
01:59:01
.
.
.
.
01:59:59
01:00:00
How can I solve this and is there a more efficient way I can do this?
Thank you.
No offence, but this is massively over-enginered. Simply store the start time when the script first runs, then subtract that from the current time every time your timer fires.
There are plenty of tutorials on converting ms into a readable timestamp, so that doesn't need to be covered here.
var start = Date.now();
setInterval(function() {
document.getElementById('difference').innerHTML = Date.now() - start;
// the difference will be in ms
}, 1000);
<div id="difference"></div>
There's too much going on here.
An easier way would just be to compare markDate to the current date each time and reformat.
See Demo: http://jsfiddle.net/7e4psrzu/
function markPresent() {
window.markDate = new Date();
$(document).ready(function() {
$("div.absent").toggleClass("present");
});
updateClock();
}
function updateClock() {
var currDate = new Date();
var diff = currDate - markDate;
document.getElementById("timer").innerHTML = format(diff/1000);
setTimeout(function() {updateClock()}, 1000);
}
function format(seconds)
{
var numhours = parseInt(Math.floor(((seconds % 31536000) % 86400) / 3600),10);
var numminutes = parseInt(Math.floor((((seconds % 31536000) % 86400) % 3600) / 60),10);
var numseconds = parseInt((((seconds % 31536000) % 86400) % 3600) % 60,10);
return ((numhours<10) ? "0" + numhours : numhours)
+ ":" + ((numminutes<10) ? "0" + numminutes : numminutes)
+ ":" + ((numseconds<10) ? "0" + numseconds : numseconds);
}
markPresent();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="timer"></div>
Here is a solution I just made for my use case. I find it is quite readable. The basic premise is to simply subtract the timestamp from the current timestamp, and then divide it by the correct units:
const showElapsedTime = (timestamp) => {
if (typeof timestamp !== 'number') return 'NaN'
const SECOND = 1000
const MINUTE = 1000 * 60
const HOUR = 1000 * 60 * 60
const DAY = 1000 * 60 * 60 * 24
const MONTH = 1000 * 60 * 60 * 24 * 30
const YEAR = 1000 * 60 * 60 * 24 * 30 * 12
// const elapsed = ((new Date()).valueOf() - timestamp)
const elapsed = 1541309742360 - timestamp
if (elapsed <= MINUTE) return `${Math.round(elapsed / SECOND)}s`
if (elapsed <= HOUR) return `${Math.round(elapsed / MINUTE)}m`
if (elapsed <= DAY) return `${Math.round(elapsed / HOUR)}h`
if (elapsed <= MONTH) return `${Math.round(elapsed / DAY)}d`
if (elapsed <= YEAR) return `${Math.round(elapsed / MONTH)}mo`
return `${Math.round(elapsed / YEAR)}y`
}
const createdAt = 1541301301000
console.log(showElapsedTime(createdAt + 5000000))
console.log(showElapsedTime(createdAt))
console.log(showElapsedTime(createdAt - 500000000))
For example, if 3000 milliseconds elapsed, then 3000 is greater than SECONDS (1000) but less than MINUTES (60,000), so this function will divide 3000 by 1000 and return 3s for 3 seconds elapsed.
If you need timestamps in seconds instead of milliseconds, change all instances of 1000 to 1 (which effectively multiplies everything by 1000 to go from milliseconds to seconds (ie: because 1000ms per 1s).
Here are the scaling units in more DRY form:
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
const MONTH = DAY * 30
const YEAR = MONTH * 12
We can also use console.time() and console.timeEnd() method for the same thing.
Syntax:
console.time(label);
console.timeEnd(label);
Label:
The name to give the new timer. This will identify the timer; use the same name when calling console.timeEnd() to stop the timer and get the time output to the console.
let promise = new Promise((resolve, reject) => setTimeout(resolve, 400, 'resolved'));
// Start Timer
console.time('x');
promise.then((result) => {
console.log(result);
// End Timer
console.timeEnd('x');
});
You can simply use performance.now()
Example:
start = performance.now();
elapsedTime = performance.now() - start;
var hours = 0;
if(minutes == 59 && seconds == 59)
{
hours = hours + 1;
minutes = '00';
seconds == '00';
}
I would use the getTime() method, subtract the time and then convert the result into hh:mm:ss.mmm format.
I know this is kindda old question but I'd like to apport my own solution in case anyone would like to have a JS encapsulated plugin for this. Ideally I would have: start, pause, resume, stop, reset methods. Giving the following code all of the mentioned can easily be added.
(function(w){
var timeStart,
timeEnd,
started = false,
startTimer = function (){
this.timeStart = new Date();
this.started = true;
},
getPartial = function (end) {
if (!this.started)
return 0;
else {
if (end) this.started = false;
this.timeEnd = new Date();
return (this.timeEnd - this.timeStart) / 1000;
}
},
stopTime = function () {
if (!this.started)
return 0;
else {
return this.getPartial(true);
}
},
restartTimer = function(){
this.timeStart = new Date();
};
w.Timer = {
start : startTimer,
getPartial : getPartial,
stopTime : stopTime,
restart : restartTimer
};
})(this);
Start
Partial
Stop
Restart
What I found useful is a 'port' of a C++ construct (albeit often in C++ I left show implicitly called by destructor):
var trace = console.log
function elapsed(op) {
this.op = op
this.t0 = Date.now()
}
elapsed.prototype.show = function() {
trace.apply(null, [this.op, 'msec', Date.now() - this.t0, ':'].concat(Array.from(arguments)))
}
to be used - for instance:
function debug_counters() {
const e = new elapsed('debug_counters')
const to_show = visibleProducts().length
e.show('to_show', to_show)
}

Running a Javascript Clock at 4x Speed [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript to run the Clock (date and time) 4 times speeder
I'm trying to make a clock that starts at a time value (hh:mm:ss) that I've supplied, and runs at 4x speed (for the server time of an online game that runs 4x actual time). I've modified a free clock that I found online to do this, but it only works for every other minute (try the code below to see exactly what I mean if that doesn't make sense).
var customClock = (function () {
var timeDiff;
var timeout;
function addZ(n) {
return (n < 10 ? '0' : '') + n;
}
function formatTime(d) {
t1 = d.getHours();
t2 = d.getMinutes();
t3 = d.getSeconds() * 4;
if (t3 > 59) {
t3 = t3 - 60;
t2 = t2 + 1;
}
if (t2 > 59) {
t2 = t2 - 60;
t1 = t1 + 1;
}
if (t1 > 23) {
t1 = 0;
}
return addZ(t1) + ':' + addZ(t2) + ':' + addZ(t3);
}
return function (s) {
var now = new Date();
var then;
var lag = 1015 - now.getMilliseconds();
if (s) {
s = s.split(':');
then = new Date(now);
then.setHours(+s[0], +s[1], +s[2], 0);
timeDiff = now - then;
}
now = new Date(now - timeDiff);
document.getElementById('clock').innerHTML = formatTime(now);
timeout = setTimeout(customClock, lag);
}
}());
window.onload = function () {
customClock('00:00:00');
};
Any idea why this is happening? I'm pretty new to Javascript and this is definitely a little hack-ey. Thanks
i take the orginal time and substract it from the current then multiply it by 4 and add it to the orginal time. I think that should take care or the sync problem.
(function(){
var startTime = new Date(1987,08,13).valueOf() //save the date 13. august 1987
, interval = setInterval(function() {
var diff = Date.now() - startTime
//multiply the diff by 4 and add to original time
var time = new Date(startTime + (diff*4))
console.log(time.toLocaleTimeString())
}, 1000)
}())
How to use with a custom date (use the Date object)
Date(year, month, day, hours, minutes, seconds, milliseconds)
var lag = 1015 - now.getMilliseconds(); is attempting to "run this again a smidge (15 ms) after the next clock tick". Make this value smaller (divide by 4?), and this code will run more frequently.
Next up, get it to show 4x the current clock duration. Similar problem: multiply now's details by 4 either inside or outside formatTime()
I would first create a Clock constructor as follows:
function Clock(id) {
var clock = this;
var timeout;
var time;
this.hours = 0;
this.minutes = 0;
this.seconds = 0;
this.stop = stop;
this.start = start;
var element = document.getElementById(id);
function stop() {
clearTimeout(timeout);
}
function start() {
timeout = setTimeout(tick, 0);
time = Date.now();
}
function tick() {
time += 1000;
timeout = setTimeout(tick, time - Date.now());
display();
update();
}
function display() {
var hours = clock.hours;
var minutes = clock.minutes;
var seconds = clock.seconds;
hours = hours < 10 ? "0" + hours : "" + hours;
minutes = minutes < 10 ? "0" + minutes : "" + minutes;
seconds = seconds < 10 ? "0" + seconds : "" + seconds;
element.innerHTML = hours + ":" + minutes + ":" + seconds;
}
function update() {
var seconds = clock.seconds += 4;
if (seconds === 60) {
clock.seconds = 0;
var minutes = ++clock.minutes;
if (minutes === 60) {
clock.minutes = 0;
var hours = ++clock.hours;
if (hours === 24) clock.hours = 0;
}
}
}
}
Then you can create a clock and start it like this:
var clock = new Clock("clock");
clock.start();
Here's a demo: http://jsfiddle.net/Nt5XN/

Categories