I want to check if 2hours passed then do some steps. This is what I've tried so far
var d = new Date();
var time = d.getHours() + d.getMinutes();
if(time >= 120) {
// Do something
}
You can use setTimeout function to do stuffs in 2 hours. To cancel the timeout task, simply use clearTimeout to stop it.
var timeoutId = setTimeout( function(){
alert( '2 hours passed' );
}, 2*60*60*1000 );
// clearTimeout( timeoutId );
I like momentjs
let twoHoursLater = moment().add({hours: 2})
after some time passes, this check will return true when 2 hours passes
moment().isAfter(twoHoursLater)
-> true
Oh, and a plugin "timer" based on moment, here
npm install moment-timer
then in javascript, use the duration and timer, like so
let timer = new moment.duration(2, 'hours').timer(callback);
timer.start();
function callback() {
/* magic happens */
}
Another simple way is to just use javascript's native timeout, in this example, a callback is invoked after 2 hours.
setTimeout(callback, 2 * 60 * 60 * 1000)
Your approach is not clear. #Thum Choon Tat answer is fine if you just want to do stuff without page refresh.Every page refresh will calculate the time from 0 second.If You want to check weather 2 hours passed or not ignoring page refresh, you have to set a reference time from which you will calculate how much time have been passed. You can use https://plugins.jquery.com/cookie/
This is Jquery Cookie to set reference time. then get current time as you are doing. now compare this current time with your reference time.
Related
I have an element #ChatStatus which is constantly changing, and when a change occurs, the element slides in being visible on screen.
What I'm trying to do now is: If there hasn't occurred any changes on this element for the last 5 seconds for example, hide the element back out of the screen. Here's my code:
$('#ChatStatus').on("DOMSubtreeModified",function(){
$('#ChatStatus').animate({'right':'30px'},500);
});
// Now I wanna run this, when the #ChatStatus is innactive, or no changes occurred
// $('#ChatStatus').animate({'right':'-200vw'},500);
Here's the full project where I want to implement this inactivity feature.
https://jsfiddle.net/shuffledPixels/77hb2do0/1/
Here is a very functional way of doing it. As your commenters have mentioned, this really isn't the best way of doing it; but if you want to, it's your code.
shouldRemove = null;
$('#ChatStatus').on("DOMSubtreeModified",function(){
clearTimeout(shouldRemove);
$(this).animate({'right':'30px'},500);
shouldRemove = setTimeout(function () {
$(this).animate({'right':'-200vw'},500);
}.bind(this), 5000);
});
I am not very experienced with JS animation and the like, so I'll leave any question of style and method choice up to you. Aside from that, I would suggest using a global variable holding the time of the last change, and polling at regular intervals to see if that time is more than 5 seconds ago. For example:
var lasttime = none
$('#ChatStatus').change(function () {
lasttime = new Date().getTime() //Set lasttime to the time when the element changed
}
setInterval(function () {
if ((new Date().getTime() - lasttime) > 5000) { //Date().getTime() is in miliseconds,
// so 5000 for five seconds
$('#ChatStatus').animate({'right':'-200vw'},500);
}
}, 1000); // Set 1000 (1 second) lower for more precision at the
// cost of more computational time
I hope this helps!
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);
I'm trying to create something similar to a stop watch in an AngularJS app.
I've got a 'start' button that when clicked, the app will set a startTime variable which gets the current time and then I want another variable which updates every second and calculates the difference in seconds between the startTime variable and the current time which I can use as the stop watch value that's displayed to the user.
I'll also need to be able to stop and restart the timer so I'd like the stop watch value to be stored in seconds so that I can easily start the timer at any number of seconds and resume the timer.
What's the simplest way of doing this?
Expanding on my comments above, something like this...
var startTime = new Date();
$scope.stopwatch = 0;
$interval(function() {
$scope.stopwatch = (new Date() - startTime) / 1000;
}, 1000);
and in your template
<p>Seconds: {{ stopwatch }}</p>
Bonus points for creating a filter for formatting the seconds in hh:mm:ss format.
The best way to accomplish this, is by using $interval like so:
var stop, seconds=0;
stop = $interval(updatingFunc, 1000);
function updatingFunc(){
seconds++;
console.log(seconds);
if(seconds === 4){ // Here you set whatever condition to cancel the interval
$interval.stop(stop);
}
}
The code I wrote to call a function on the minute every minute, I think is flawed, as It's good for a while, but tends to lag behind by about 15 seconds for every hour since the page was loaded. To be honest I can't figure out what's causing the lagging, maybe it's the time it takes the functions to execute, small lapses all adding up and accumulating. Is there a way to auto-correct the lapses within the function as it's called. Or maybe someone knows a better method of achieving on the minute function calls. Any help or ideas much appreciated. Thanks.
var now = new Date();
var delay = 60 * 1000; // 1 min in msec
var start = delay - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function setTimer() {
onTheMinFunc();
setTimeout(setTimer, delay);
}, start);
First of all, the DOM Timers API does not guarantee accuracy. I quote:
This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected.
Second, you have a lag on each round caused by the time onTheMinFunc() is executed (you only set the timeout when it's done).
So, let's say onTheMinFunc takes half a second to execute - you get half a second delay at each minute and it accumulates - after only 10 minutes it'll lag quite a bit. (Note, functions should usually not take more than 15ms to execute anyway to avoid noticeable lag)
Try:
setInterval(onTheMinFunc, delay);
It still won't be very accurate. You can poll on much shorter intervals and keep track of a date variable - but again - no guarantees.
What you probably want is setInterval:
setInterval(onTheMinFunc, delay);
As is, your code using setTimeout means that the time it takes to execute your onTheMinFunc is being added into your delay before the next one is started, so over time, this extra delay will add up.
Using setInterval will be more accurate, since the delay is between calls to execute the function, rather than starting the timer only after the function is finished.
Timers and javascript times aren't very accurate, and I would think the only way to make sure a function is executed every whole minute over time, is to check the seconds every second
setInterval(function() {
if ( new Date().getSeconds() === 0 ) onTheMinFunc();
},1000);
FIDDLE
Here is a slight modification to your code:
function everyMinute(fn) {
arguments[1] && fn();
var now = new Date();
var delay = 60 * 1000 - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function(){
everyMinute(fn, true);
}, start);
}
everyMinute(onTheMinFunc);
It recalculates the number of milliseconds to wait till the next minute every time so it is as accurate as possible to the top of the minute.
I think you want something closer to this:
function setNextMinute() {
// figure out how much time remains before the end of the current minute
var d = new Date().getTime()%60000;
//set a timeout to occur when that expires.
setTimeout(function () {
// recalculate a new timeout so that your timer doesn't lag over time.
doWhateverYouWantToHere();
// note that calling doWhateverYouWantToHere() will
// not offset the next minute, since it is recalculated in setNextMinute()
setNextMinute();
},60000-d);
}
setNextMinute();
caveat: I did not thoroughly test this for timing. But it appeared to work for 1 sec intervals and 1 min intervals well enough.
This has the advantage of not recalculating every second, and also not just starting a 60 second timer from whatever the current time is.
The current accepted answer may overkill
Executing if ( new Date().getSeconds() === 0 ) onTheMinFunc(); on each second (and forever) seems to not be a good idea.
I will not benchmark it against the following propositions, it's not necessary.
Clues
Use whatever logic is necessary to calculate the start moment.
On the start moment
Use setInterval for remaning executions
Execute the first call
Note setInterval is called ASAP to avoid that time lapses.
If you want that new Date().getSeconds() === 0:
var id = setInterval(function() {
if ( new Date().getSeconds() === 0 ) {
setInterval(onTheMinFunc, delay);
onTheMinFunc();
clearInterval(id);
}
},1000);
Alternatively, you could use your own logic:
var now = new Date();
var delay = 60 * 1000; // 1 min in msec
var start = delay - (now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function() {
setInterval(onTheMinFunc, delay);
onTheMinFunc();
}, start);
Please check both examples working on jsfiddle
The second (Example B) seems more accurate.
I was just wondering if it is possible to have a javascript for loop that only iterates through the loop once a day i.e. when the date changes?
for(i=0; i < myArray.length; i++){
alert(myArray[i]);
}
So in the above loop, let it run, and freeze it or something only till the data changes, and the do another iteration, and just keep on doing that.. You know what I mean.
Thanks in advance!
Using localStorage is the best way to go when you don't have a server (because a user can change the computer's time and break your logic, and using a server it's harder to hack this)
Method below is more bulletproof:
// checks if one day has passed.
function hasOneDayPassed()
// get today's date. eg: "7/37/2007"
var date = new Date().toLocaleDateString();
// if there's a date in localstorage and it's equal to the above:
// inferring a day has yet to pass since both dates are equal.
if( localStorage.yourapp_date == date )
return false;
// this portion of logic occurs when a day has passed
localStorage.yourapp_date = date;
return true;
}
// some function which should run once a day
function runOncePerDay(){
if( !hasOneDayPassed() ) return false;
// your code below
alert('Good morning!');
}
runOncePerDay(); // run the code
runOncePerDay(); // does not run the code
If you want something to happen at predefined intervals, you can set a timeout/interval:
http://www.w3schools.com/js/js_timing.asp
For example:
var dayInMilliseconds = 1000 * 60 * 60 * 24;
setInterval(function() { alert("foo"); },dayInMilliseconds );
edit: since you mentioned that the code will be running in a browser, this assumes the browser is running for at least 24 hrs and will not work otherwise.
the best way to achieve it is by creating a cookie that lasts for1 day..
Even if after the refresh of the web page or browser gets closed that countdown will still continue..
setcookie($cookie_name, $cookie_value, time() + 86400, "/");
This means 86400 = 1 day
Hope it helps