Javascript: how to run timer at every "ROUND" x seconds? - javascript

I need to run my javascript timer in every 5 seconds, but only then, when the current time is at "round" 5 seconds (I mean when the second value is divisible by 5.) So, I want to set the start time to "round" 5 seconds.
Not good, when the second is (for example): 7, 12, 17, 22 etc ...
Good: 0, 5, 10, 15 etc ...
My current code (runs well in every 5 seconds, but the start is not set to "round" 5 seconds):
<script type="text/javascript">
window.setInterval(function(){
draw();
}, 5000);
</script>
Please, help me.

Get the actual date and extract seconds*1000 and milliseconds. Modulo 5.000 gets ms from last 5s interval subtract this from 5.000 and you get the first start.
Start the first time with setTimeout and after this every 5.000 ms with setInterval.
let date = new Date();
let ms = date.getSeconds()*1000 + date.getMilliseconds();
let start = 5000 - (ms %5000);
//console.log(ms, start);
setTimeout(function(){
doIt();
window.setInterval(doIt, 5000);
}, start);
function doIt() {
console.log('Boom');
}

You can do a loop every 1 sec, to check if modulus of getUTCMinutes() / 5 == 0, and once it does, then execute your script.. so it will START at that 5 min mark, and then continue on it's own..

Use recursive setTimeouts instead, which measures the time between now and the next "round" seconds number:
const scheduleDraw = () => {
const now = new Date();
const secondsToNext = 5 - (now.getSeconds() % 5);
const millisecondsToNext = ((secondsToNext - 1) * 1000) + (1000 - now.getMilliseconds());
setTimeout(draw, millisecondsToNext);
};
const draw = () => {
console.log('drawing at', new Date());
scheduleDraw();
};
scheduleDraw();
Don't use setInterval - it'll get inaccurate after a while, especially if the user switches browser tabs. Better to calculate the new timeout every time.

The idea is to have a function that reads out the system time, and determines how much time is left for the next 5 second moment, and triggers a corresponding setTimeout for that.
You should allow for a few milliseconds of variation though:
function callAt5(callback) {
let now = new Date();
let milli = (now.getMilliseconds() + 1000 * now.getSeconds()) % 5000;
setTimeout(callAt5.bind(null, callback), 5000 - milli);
if (milli < 100) callback();
}
// pass the callback which you want to execute at each 5 second mark:
callAt5(() => console.log(new Date));

Related

Check if specified time is mentioned in an incremented time

Here are some of the variables I have:
start time: 10:45
interval time: 5 (in minutes)
specific time: 14:20
I need to find out if the specific time lands exactly on any of the times incremented from the start time.
For example, the interval time is 5.
10:45 incremented by interval time
11:00
11:05
11:10
...
14:20 << specific time found
if(specificTime is mentioned in any of the incremented times) {
console.log('Found it!');
} else {
console.log('Not found');
}
But this is hard when the start time is 10:48 and the interval time is 5 minutes. Because:
10:48
10:53
10:58
11:03
11:08
...
and 14:20 is not mentioned in this one, so it would log "Not found".
How can I find out if the specific times is mentioned in the incremented times from the start time?
The interval time will not always be 5 and the other variables will be dynamic as well.
I am NOT looking to use loops. There has to be a formula or function that can help me achieve this. Thanks!
I think you can calculate if it is possible to perform a restless division of the difference between the start time and the specified time and the interval.
Depending on the scale of your time intervals, you can calculate this in hours, minutes, seconds, milliseconds or basically any scale. Since your examples deal in minutes, the code snippet also does.
Note that this snippet assumes both times are within the same day (00:00 - 24:00) and that the specific time is later within that day than the start time. I'll let you figure out the rest :)
function toMinutes(hours, minutes) {
return (hours * 60) + minutes;
}
const startTime = toMinutes(10, 45);
const specificTime = toMinutes(14, 20);
const interval = toMinutes(0, 5);
const difference = specificTime - startTime;
if (difference % interval === 0) {
console.info('Found it!');
console.info('Minutes:', difference);
console.info('Intervals:', difference / interval);
} else {
console.error('Not found');
}
This works by:
- Turning the time strings into numeric minutes (with countOfMinutes())
- Subtracting startTime from specificTime (and adjusting if we increment past 12:00)
- Dividing the result by minsPerIncrement and checking whether the remainder is zero
// The big payoff -- calculates whether we exactly hit `specificTime`
function isExact(start, specific, increment){
let difference = countOfMinutes(specific) - countOfMinutes(start);
if(difference <= 0){ difference += 12 * 60; } // Add 12 hours if necessary
return difference % increment == 0;
}
// The converter -- because numbers are easier to divide than strings
function countOfMinutes(timeString){
const hours = timeString.slice(0, timeString.indexOf(":"));
const mins = timeString.slice(timeString.indexOf(":") + 1);
return hours * 60 + mins;
}
// The results -- some readable output
function report(){
console.log(`
Repeatedly adding ${minsPerIncrement} to ${startTime} will eventually yield ${specificTime}?:
_ ${isExact(startTime, specificTime, minsPerIncrement)} _`);
}
// The pudding -- a couple of test cases
let start, specific, minsPerIncrement;
startTime = "12:30"; specificTime = "3:55"; minsPerIncrement = 21;
report();
startTime = "4:20"; specificTime = "11:45"; minsPerIncrement = 5;
report();
startTime = "11:45"; specificTime = "4:20"; minsPerIncrement = 5;
report();

Making a min:sec counter using javascript

I am trying to make a small question/answer quiz game using react, and I want to show a timer that counts down every second. Each game will last 10, 15, or 30 minutes at most, so I want to show a timer that updates every second in the bottom of the screen (in big font, of course!), something like 15:00, 14:59, 14:58, and so on until it hits 00:00.
So, given a start time such as 2016-04-25T08:00:00Z, and an end time after adding 15 min of 2016-04-25T08:15:00Z, I want to start the countdown.
My issue is that I am not understanding how to use setIntervals to keep calling my method to find the remaining time.
timeLeft = Math.round(timeLeft/1000) * 1000;
const timer = new Date(timeLeft);
return timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
EDIT: You've edited your question. You will need the time padding, and the method below will be faster than what you are using, but to answer your question about setInterval:
First, define your function to run your timer and decrement each time it's called:
var timeLeft; // this is the time left
var elem; // DOM element where your timer text goes
var interval = null; // the interval pointer will be stored in this variable
function tick() {
timeLeft = Math.round(timeLeft / 1000) * 1000;
const timer = new Date(timeLeft);
var time = timer.getUTCMinutes() + ':' + timer.getUTCSeconds();
elem.innerHTML = time;
timeLeft -= 1000; // decrement one second
if (timeLeft < 0) {
clearInterval(interval);
}
}
interval = setInterval(tick, 1000);
OG Answer:
No, I do not believe there is a built-in way to display time differences.
Let's say you have two date objects:
var start = Date.now();
var end = Date.now() + 15 * 60 * 1000; // 15 minutes
Then you can subtract the two Date objects to get a number of milliseconds between them:
var diff = (end - start) / 1000; // difference in seconds
To get the number of minutes, you take diff and divide it by 60 and floor that result:
var minutes = Math.floor(diff / 60);
To get the number of seconds, you take the modulus to get the remainder after the minutes are removed:
var seconds = diff % 60;
But you want these two padded by zeros, so to do that, you convert to Strings and check if they are two characters long. If not, you prepend a zero:
// assumes num is a whole number
function pad2Digits(num) {
var str = num.toString();
if (str.length === 1) {
str = '0' + str;
}
return str;
}
var time = pad2Digits(minutes) + ':' + pad2Digits(seconds);
Now you have the time in minutes and seconds.

Javascript compare 2 dates and result must be setTimeout() Method in ms

I'm trying to compare to 2 dates by hour/minutes/seconds, in order to make a script to resume a script when closed. If current time is pass closed time + interval ( currently set at 30 minutes) should execute and run the script normally, if not wait till difference timeouts to execute.
Current hour/minutes/seconds is not a must but the result should be in ms interval
Example:
interval = (30 * 60 * 1000)
close time = 15:10:53
current time = 15:15:29
close time + interval = 15:40:53
first time I check if `current time` <= `close time + interval`
then calculate `difference`
`difference` = (close time + interval = 15:40:53) - (current time = 15:15:29)
Result should be setTimeout(function(){ alert("Hello"); }, time difference);
The only way I'm thinking of doing this is calculate each difference from Hour,Minutes,Seconds and then finding out the ms for setTimeout
I tried but results were weird, not something that would count as smaller than 30min
var ONE_S = 1000 ;
var timeDiff = Math.abs(closeTime - currentTime);
var diffS = Math.round(timeDiff/ONE_S)
Use Date objects and compare timestamps like so:
var interval = 30 * 60 * 1000;
var closeTime = new Date('Wed Nov 26 2015 10:17:44 GMT-0400 (AST)');
var currentTime = new Date;
var difference = (closeTime - currentTime) + interval;
if(difference < 0) {
console.log('time has expired');
}else{
setTimeout(someFunction, difference);
}
closeTime - currentTime gets the time between timestamps in ms, which will be negative if it's past closing time. We offset closing time by 30 minutes (by adding interval). Then we just have to check if difference < 0 to know if time has expired, and if not we can wait difference milliseconds to trigger someFunction

How to call a function every hour?

I am trying to update information from a weather service on my page. The info should be updated every hour on the hour. How exactly do I go about calling a function on the hour every hour?
I kind of had an idea but I'm not sure of how to actually refine it so it works...
What I had in mind was something like creating an if statement, such as: (pseudo code)
//get the mins of the current time
var mins = datetime.mins();
if(mins == "00"){
function();
}
You want to check out setInterval: https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval
It's a little hard to tell what you're trying to call with your code, but it would be something in the form of:
function callEveryHour() {
setInterval(yourFunction, 1000 * 60 * 60);
}
If you want it every hour, try something like:
var nextDate = new Date();
if (nextDate.getMinutes() === 0) { // You can check for seconds here too
callEveryHour()
} else {
nextDate.setHours(nextDate.getHours() + 1);
nextDate.setMinutes(0);
nextDate.setSeconds(0);// I wouldn't do milliseconds too ;)
var difference = nextDate - new Date();
setTimeout(callEveryHour, difference);
}
Now, this implementation checks the time once, sets the delay (or calls the function immediately), and then relies on setInterval to keep track after that. An alternative approach may be to poll the time every x many seconds/minutes, and fire it .getMinutes() == 0 instead (similar to the first part of the if-statement), which may sacrifice (marginal) performance for (marginal) accuracy. Depending on your exact needs, I would play around with both solutions.
Here is what should work (JSFiddle):
function tick() {
//get the mins of the current time
var mins = new Date().getMinutes();
if (mins == "00") {
alert('Do stuff');
}
console.log('Tick ' + mins);
}
setInterval(tick, 1000);
What you probably want is something like that:
var now = new Date();
var delay = 60 * 60 * 1000; // 1 hour in msec
var start = delay - (now.getMinutes() * 60 + now.getSeconds()) * 1000 + now.getMilliseconds();
setTimeout(function doSomething() {
// do the operation
// ... your code here...
// schedule the next tick
setTimeout(doSomething, delay);
}, start);
So basically the first time the user get the access, you need to know what is the delay in millisecond to the next "hour". So, if the user access to the page at 8:54 (with 56 seconds and 123 milliseconds), you have to schedule the first execution after around 3 minutes: after the first one is done, you can call it every "hour" (60 * 60 * 1000).
Repeat at specific minute past the hour
This counter is a little bit more versatile; it allows to perform a task repeatedly always at the same minute past the hour (e.g. 37 minutes past the hour), and this with up to millisecond precision.
The precision of this timer is derived from its recursion.
At every recursion, the millisecond time to the next minute gets recalculated. This prevents time lag over long periods.
The % sign refers to the modulo operator.
function minuteCount(minutesAfterHour) {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const milliseconds = now.getMilliseconds();
waitUntilNextMinute = setTimeout(minuteCount, 60000 - seconds * 1000 - milliseconds);
if(minutes % 60 === minutesAfterHour) {
doSomethingHourly();
}
}
minuteCount(37);
Finally, timers are best kept away from the main thread. They are best run from within a web worker, as explained here.
This works perfectly with unfocused tabs in desktop browsers.
However, dedicated web workers on Chrome for Android are put to sleep about 5 minutes after moving the main client to the background.
EDIT: Oops, I didn't see the " o' clock" things, so I edit my answer :
var last_execution = new Date().getTime();
function doSomething(force){
var current_time = new Date().getTime();
if (force || (current_time.getMinutes() == 0)
{
last_execution = current_time;
// something
// ...
}
setTimeout(doSomething(false), 1000);
}
// force the first time
doSomething(true);
// ... call your func now
let intervalId;
let timeoutId = setTimeout(() => {
// ... call your func on end of current hour
intervalId = setInterval(() => {
// ... call your func on end of each next hours
}, 3600000);
}, ((60 − moment().minutes()) × 60 × 1000) - (moment().second() * 1000));
Here is my pair of setIntervalWithDelay and clearIntervalWithDelay that one can use like this:
let descriptor = setIntervalWithDelay(callback, 60 * 60 * 1000, nextHourDelay)
And when you are done with it:
clearIntervalWithDelay(descriptor)
Here is my implementation of the functions:
const setIntervalWithDelay = (callback, interval, delay = 0) => {
let descriptor = {}
descriptor.timeoutId = setTimeout(() => {
if(!descriptor.timeoutId){
return
}
descriptor.timeoutId = null
callback()
descriptor.intervalId = setInterval(callback, interval)
}, delay)
return descriptor
}
export const clearIntervalWithDelay = (descriptor) => {
if(!isObject(descriptor) || (!descriptor.timeoutId && !descriptor.intervalId)){
console.warn("clearIntervalWithDelay: Incorrect descriptor. Please pass an object returned by setIntervalWithDelay. Skipping this call.")
return
}
if(descriptor.timeoutId){
clearTimeout(descriptor.timeoutId)
descriptor.timeoutId = null
console.log("clearIntervalWithDelay: stopped during delay.")
}
if(descriptor.intervalId){
clearInterval(descriptor.intervalId)
descriptor.intervalId = null
console.log("clearIntervalWithDelay: stopped during interval repeat.")
}
}
One example of using dayjs to get the delay for the next hour:
let nextHour = dayjs().second(0).millisecond(0).add(1, "hour")
let nextHourDelay = nextHour.diff(dayjs())

Executing code inside setInterval function only once per few seconds

I'm working on a simple project that is HTML and Javascript; and I have a problem with my timer.
I'm calculating the seconds between two Date() objects; and every 2 seconds, I want to get a new random number. I have a setInterval that runs every 100 ms and when I get past the 2 second mark, the code inside the if statement should run.
So my question is:
How can I make sure the code execute only once per 2 seconds in an if statement that is inside a setInterval() that runs every 100 ms?
Here is the code:
var startTime = new Date();
var endTime = new Date();
var randomNumber = 0;
var gameTimer = setInterval(function(){
//calculate seconds;
var secondsPassed = Math.round( (endTime - startTime) / 1000 );
if(modulo(secondsPassed,2) == 0){
//when the "gate" is open this keep executing every 100 mili seconds.
//but i want it to execute only once every 2 seconds.
randomNumber = Math.floor(Math.random()*lanes.length);
$(lanes[randomNumber]).append(box);
}
endTime = new Date();
}, 100);
var modulo = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
I think you are asking for a double-interval timer.
var interval = 100, beat = 2000, ticks = 0;
var timer = setInterval(function(){
runsEvery100ms(); // ««« Code here runs every 100 ms.
if (ticks > 0 && ticks % beat === 0) {
runsEvery2000ms(); // ««« Code here runs every 2000 ms.
ticks = 0;
}
ticks += interval;
}, interval);
Demo Fiddle here.

Categories