I am updating a clock once every second, the time comes from a new Date object, but I am wondering if it is better to simply add upon an initial time with setInterval or to create a new Date every second and work with that object to update the time.
They both work, but I am wondering if it is responsible to be creating a new object every second, since I am sure the setInterval() method would use a considerably smaller amount of resources since three functions are executed when getting time. (.getHours(), .getMinutes(), .getSeconds())
I can see an advantage in having it use a new Date object, as I assume it would change when the systems time changes (changing timezone or daylight savings adjustments).
So is it more efficient to use setInverval() or would it use just as many resources as creating a new Date object each time?
setInterval(function myFunc(){}, 1000) does not guarantee, that myFunc will be called every second. In fact, the inteval can vary heavily. For example, in Chrome, if you change tab, the interval will slow down a lot, until you return to the initial tab.
So keep using new Date().
See http://javascript.info/tutorial/settimeout-setinterval
Use this , it will help you, in order to display the time at only once after your page getting loaded you simply can use the new Date() and the getHours(),getMinutes,getSeconds function. In order to display the updated time without making the page to refresh you need to use both setInterval(), and new date() functionalities together.you need to use new date() inside set interval because, if you add any alert in side you code then it will not pause your time updation.
function pad(str, max) {
return ((str.length < max) ? pad("0" + str, max) : str);
}
var d;
setInterval(function myFunc() {
d = new Date();
document.getElementById("date").innerText = (pad(d.getHours().toString(), 2) + ":" + pad(d.getMinutes().toString(), 2) + ":" + pad(d.getSeconds().toString(), 2));
}, 1000);
<div id="date"></div>
Related
I am implementing a live clock in front-end of a large application. For that I have came up with following approach -
JavaScript
var span = document.getElementById('span');
function time() {
var d = new Date();
var s = d.getSeconds();
var m = d.getMinutes();
var h = d.getHours();
span.textContent = h + ":" + m + ":" + s;
}
setInterval(time, 1000);
HTML
<span id="span"></span>
This approach works perfectly fine in isolation, but when this code is integrated in the application which is having several events and function calls, the clock starts lagging by few minutes after say couple of hours until the page is refreshed.
I think this delay is because of setInterval being a web (browser) API and is handled asynchronously it may not execute exactly after 1 second as written in the code every time, if the call stack is not empty after 1 second from time being setInterval is registered due to other function calls/ events present in the call stack of event loop.
So if the page is not refreshed for long time the delay continues to grow. Also the application is written in Angular which is a Single Page application where the page never reloads on navigation because of routing until the page is forcefully refreshed.
So how to build a precise clock in JavaScript which will never delay when integrated in a large application?
Update: Thanks everyone for the response. I think some of you are right, I may be missing some of the details. Actually I was implementing this few days back at work, but have to left this due to some reason and lost track of it. But there was some delay issue for sure working with Date and Timers. Suddenly now this came to my mind and thought asking it here. Extremely sorry for not providing concrete details.
Still I will try to recollect the details and update the question accordingly if possible.
the clock starts lagging by few minutes after say couple of hours until the page is refreshed.
Thats impossible with the code you've shown, new Date should return the correct time, no matter how often you reflect its value to the page.
So if the page is not refreshed for long time the delay continues to grow.
Most browsers today will adjust the timers slightly, so that they are quite accurate on average (e.g. if one timer gets called to late by 1ms, the next will be called 1ms earlier), therefore you can only cause a drift over a longer time if you will leave the page, which will pause the timer. That still shouldn't affect new Date though.
Have a look at the Chromium source
Timers in web browsers get dialled back when the page doesn't have focus. You can't change or prevent that. You're already doing the primary thing that's important: Using the current time to update the clock, so that even if your time function isn't called for three seconds, when it runs it updates with the then-current time, skipping over the intermediate values. (You often see people assuming the timer will run at exactly 1000ms intervals and just adding to the seconds value rather than using the current time, which is incorrect.)
If I were doing this, I'd probably decrease the interval (run the callback more often) and use a chained series of setTimeout rather than a single setInterval, not least because different browsers have historically handled setInterval in different ways.
So for instance:
function time() {
var d = new Date();
var s = d.getSeconds();
var m = d.getMinutes();
var h = d.getHours();
span.textContent = h + ":" + m + ":" + s;
setTimeout(time, 250);
}
time();
But if the page is inactive, the clock will get out of date, because the browser will either completely suspend timer execution or at least markedly dial it back. When the page becomes active again, though, hopefully it'll correct itself after no more than 250ms.
I am trying to compare the time now and a time in a future date. When these times are the same I want to show a message. However, the code below is not working. I have been checking the console and now.getTime() is never the same as end.getTime(), presumably as they are in ms?
Does anyone know how to overcome this? Following this answer here I believe it should work.
function compareTimes() {
var end = new Date("August 31, 2016 11:04:18");
var now = new Date();
if (now.getTime() == end.getTime()) {
clearInterval(timer);
document.getElementById('countup').innerHTML = 'EXPIRED!';
return;
}
}
setInterval(compareTimes, 1000);
setInterval will execute the function compareTimes every second and your function will compare the times at that very instant. It is highly unlikely that both the times will be same, hence you won't be able to set your div to EXPIRED . In order to overcome this i suggest you check if the time is greater than the current time i.e if (now.getTime() > end.getTime()) then set the state as EXPIRED in your div.
I'm trying to decrement a variable once a day. I have written the following code for that.
var counter = 10; //any value
setInterval(function() {
counter = counter - 1;
}, 86400000);
Is there a better or efficient way to achieve the same thing ?
P.S : - I do not wish to use any libraries.
The only thing I see you miss is to set the initial value of counter variable.
I would write:
var counter = 1000; // or any useful value
setInterval(function() {
--counter;
}, 24 * 60 * 60 * 1000); // this is more self-explanatory than 86400000, and, being evaluated just once, it will have a tiny effect on the performace of the script
I don't see any problem in the way you write it. You use interval, ok, but this is not the worst evil you may do to set up the variable value.
You may think of another solution with a function which returns you the current counter.
var initialValue = 20000;
function getCounter() {
return initialValue - Math.floor(Date.now() / 1000 / 60 / 60 / 24);
}
console.log(getCounter());
The difference is that it takes the current day number starting from the UNIX time beginning. Every day the day number will be increased, so the result of the function will be decreased by 1.
But still I don't see how this solution can be better than yours.
I'm not totally sure why, but using setInterval like this makes me uncomfortable.
If I were to require this, I would use something like this approach:
var counter = 10;
var timeout = new Date();
setInterval(function(){
if(new Date() >= timeout)
{
--counter; // the action to perform
timeout = new Date(timeout.getTime() + 86400000); // update the timeout to the next time you want the action performed
}
console.log(counter);
},1000); // every second is probably way more frequent than necessary for this scenario but I think is a decent default in general
One thing that this allows is to, for example, set the next timeout to midnight of tomorrow rather than being locked in to "X seconds since the previous execution". The key is the inversion of control - the action itself can now dictate when it should next run.
Though I would probably abstract away the details behind an interface accepting a start, interval, and action.
The biggest problem in my eyes is that you have to keep this one JS process running consistently for days at a time to have it do what you need. The world is not so perfect that things don't need an occasional reboot...including the average JS process.
Personally I would store a timestamp of my starting point, then (whenever I need to know how much time has elapsed) grab a new timestamp and use it to calculate how many days it has been. That way even if something interrupts my process I can still be right where I started.
Maybe use window.localStorage to save the last time, and if it is greater than 60*60*24 (seconds in a day) set the last time to this morning/now/1:00 and then decrease the value and save it.
Example:
var d = new Date();
var mins = -(1+d.getHours())*60+d.getMinutes();
var secs = mins*60+d.getSeconds(); // total seconds passed today from 1:00
var now = d.getCurrentTime():
var lastCheck = localStorage.getItem("lastCheck");
if (!lastCheck)
{
localStorage.saveItem("lastCheck",now-secs); // beginning of today
}
var dayPassed = now - lastCheck > 24*60*60; // change to see if a day has passed
if (dayPassed)
{
// save seconds
localStorage.setItem("counter",localStorage.getItem("counter")-1);
localStorage.saveItem("lastCheck",now-secs); // beginning of today
}
It makes more sense to me to check how many days have passed since a specific date and decrement that number of days from the counter. Mostly just because I wouldn't expect anybody to leave the same page open without the need or want to reload for days on end. I would do something like this:
counter = 365; // original counter
var start = new Date(2016, 03, 20); // original date
var now = new Date();
var days = Math.floor(Math.abs(start.getTime()-now.getTime())/(24*60*60*1000))
counter -= days;
That way every time you visited the page, it would be decremented correctly. Note that this ignores any issues with leap days or time zones. The example above would have a counter of 360 for me. And then if you did expect it to be open for days, reload it automatically with:
self.setTimeout(function(){document.location.reload()}, 86400000);
What’s the best way to get monotonically increasing time in JavaScript? I’m hoping for something like Java’s System.nanoTime().
Date() obviously won’t work, as it’s affected by system time changes.
In other words, what I would like is for a <= b, always:
a = myIncreasingTime.getMilliseconds();
...
// some time later, maybe seconds, maybe days
b = myIncreasingTime.getMilliseconds();
At best, even when using the UTC functions in Date(), it will return what it believes is the correct time, but if someone sets the time backward, the next call to Date() can return a lesser value. System.nanoTime() does not suffer from this limitation (at least not until the system is rebooted).
Modification: [2012-02-26: not intended to affect the original question, which has a bounty]
I am not interested knowing the “wall time”, I’m interested in knowing elapsed time with some accuracy, which Date() cannot possibly provide.
You could use window.performance.now() - since Firefox 15, and window.performance.webkitNow() - Chrome 20]
var a = window.performance.now();
//...
var delay = window.performance.now() - a;
You could wrap Date() or Date.now() so as to force it to be monotonic (but inaccurate). Sketch, untested:
var offset = 0;
var seen = 0;
function time() {
var t = Date.now();
if (t < seen) {
offset += (seen - t);
}
seen = t;
return t + offset;
}
If the system clock is set back at a given moment, then it will appear that no time has passed (and an elapsed time containing that interval will be incorrect), but you will at least not have negative deltas. If there are no set-backs then this returns the same value as Date.now().
This might be a suitable solution if you're writing a game simulation loop, for example, where time() is called extremely frequently — the maximum error is the number of set-backs times the interval between calls. If your application doesn't naturally do that, you could explicitly call it on a setInterval, say (assuming that isn't hosed by the system clock), to keep your accuracy at the cost of some CPU time.
It is also possible that the clock will be set forward, which does not prevent monotonicity but might have equally undesirable effects (e.g. a game spending too long trying to catch up its simulation at once). However, this is not especially distinguishable from the machine having been asleep for some time. If such a protection is desired, it just means changing the condition next to the existing one, with a constant threshold for acceptable progress:
if (t > seen + leapForwardMaximum) {
offset += (seen - t) + leapForwardMaximum;
}
I would suggest that leapForwardMaximum should be set to more than 1000 ms because, for example, Chrome (if I recall correctly) throttles timers in background tabs to fire not more than once per second.
Javascript itself does not have any functionality to access the nanoTime. You might load a java-applet to aqcuire that information, like benchmark.js has done. Maybe #mathias can shed some light on what they did there…
Firefox provides "delay" argument for setTimeout...
this is the one of ways to implement monotonically increased time counter.
var time = 0;
setTimeout(function x(actualLateness) {
setTimeout(x, 0);
time += actualLateness;
}, 0);
I was reading up on this javascript tutorial:
http://www.switchonthecode.com/tutor...ccordion-menus
Basically, it shows you how to create an accordion using pure javascript, not jquery. All made sense to me until the actual part of tracking the animation. He says "Because of all that, the first thing we do in the animation function is figure out how much time has passed since the last animation iteration."
And then uses this code:
Code:
var elapsedTicks = curTick - lastTick;
lastTick is equal to the value of when the function was called (Date().getTime()) and curTick is equal to the value when the function was received. I don't understand why we are subtracting one from the other right here. I can't imagine that there's any noticeable time difference between these two values. Or maybe I'm missing something. Is that animate() function only called once every time a menu title is clicked or is it called several times to create the incremental animation effect?
setTimeout("animate(" + new Date().getTime() + "," + TimeToSlide + ",'" + openAccordion + "','" + nID + "')", 33);
Thanks for any response.
lastTick is equal to the value of when the function was called
lastTick is equal to the value when the function was previously called, on the last frame of animation. Since then, the script has given control back to the browser, asking to be called back in 33 milliseconds.
So curTick-lastTick will generally be about 33, but it could be much higher if the browser is lagged due to other stuff happening at the same time. This is why time-reading has to be done at all.
More usually in this sort of code, you'd store the time the animation started in a variable, and use setInterval to check it every so often, instead of setting a complete new timeout function each time (especially setting a timeout from a string, which is super-ugly).
eta:
then runs the animate() function, which passes the current time
Nope. Look at the set-timeout call again:
setTimeout("animate(" + new Date().getTime() + ","...
That's making a string. new Date().getTime() is evaluated at timeout-setting time, not at timeout-calling time. It ends up making a string like:
setTimeout("animate(1275139344177, 250, 'Accordion4Content', 'Accordion4Content')", 33)
Which is the time at the end of the last frame, not the time the next frame's timeout will fire.
Putting JavaScript code in a string like this is super-confusing, rife with escaping problems, and generally regarded as really poor practice. It would be clearer to do it with an inline function:
var passTick= new Date().getTime();
setTimeout(function() {
animate(passTick, TimeToSlide, openAccordion, nID);
}, 33);