how can I schedule an api call on every quarter? - javascript

I want to send some user specific data to an API on every quarter after a user logs in. like every 9:15 then 9:30 then 9:45 and so on..
I can use setInterval for every 15 min but I want it to be exactly at the quarter.
For Example - A user logs in at 9:25, so instead of hitting the API after 15 min(9:40) from then I want it to hit at 9:30 and then 9:45 and so on..
How can I achieve this?

you can simply check every minute if minutes % 15 == 0 and then hit your API

Use Date to calculate time to next 15, 30, 45, 60 minute clock,
Use setTimeout to set a timer to the calculated time,
Start a new interval using setInterval.
function onEveryQuarter(callbackFn) {
// function that starts an interval that calls `callbackFn()` every 15 minutes
const startQuarterInterval = () => setInterval(callbackFn, 60*1000*15); // in milliseconds
// get minutes to next :15, :30, :45, :60 time
const now = new Date();
const nextQuarterTime = Math.abs(now.getMinutes() % 15 - 15) * 1000; // *1000 to convert to milliseconds
// start timer
const quarterTimer = setTimeout(startQuarterInterval, nextQuarterTime);
}
And then,
// desired function
const myFunc = () => console.log("hello world");
// to execute `onEveryQuarter` as soon as user visits your site.
window.onload = (e) => onEveryQuarter(myFunc);
at top of your main.js file.

Related

Run function on a specific UTC +5:30 Time once

I have a function main().
I want to run this function at times 9:25,1:25,5:25 (considering 12 hour clock time-means 9:30 in the morning as well as at the night).
As the clock hits any of the times mentioned above, the function should run once. Then the function should wait for next time.
Like function runs at 9:30 in the morning (but only once and then stops) then it should wait for 1:25 in the afternoon. I want all this to be coded in Javascript. Is there any scheduler which will help me...
Do something like this:
var times = [[9, 25], [1, 25], [5, 25]];
var lastrun;
function checktime(){
now = new Date(); // Get the current time
if (lastrun != null){
if (now-lastrun > 60000) return; // Wait until a minute has elapsed
// (In order to avoid the function running twice within the same minute)
}
ok = false;
for (time of times){ // Iterate through target times
target = new Date(); // Create a new date where the target time will be held
target.setHours(time[0]); // Set the hour and minute to the target time
target.setMinutes(time[1]);
if (now.getTime() >= target.getTime()){ // Check if the target time has been reached
ok = true;
break;
}
}
if (ok){
lastrun = now; // Store the time when the function was last run
main(); // Run the main function if 'ok' is true
}
}
setInterval(checktime, 1000);

Reseting a variable value everyday at midnight in node js

I have a global var in my node js code. I need to reset its value to 1 everyday midnight at 12am. How is it done in node js?
I have read certain articles about node scheduler. Does it work or there are any other ways?
You can use a simple setTimeout() to schedule it yourself:
let myVar = 10;
function scheduleReset() {
// get current time
let reset = new Date();
// update the Hours, mins, secs to the 24th hour (which is when the next day starts)
reset.setHours(24, 0, 0, 0);
// calc amount of time until restart
let t = reset.getTime() - Date.now();
setTimeout(function() {
// reset variable
myVar = 1;
// schedule the next variable reset
scheduleReset();
}, t);
}
scheduleReset();
Any time your program starts, it can just call scheduleReset().
FYI, I lifted most of this code from a program I wrote (on a Raspberry Pi server) that restarts itself at 4am every night and that program has been doing that successfully for several years.
Using node-schedule this should be straightforward. Define your job with the correct cron-tab and reset the variable to the default value in the scheduleJob-callback:
const schedule = require('node-schedule');
let yourVar = 12345;
const globalResetJob = schedule.scheduleJob('0 0 * * *', () => {
yourVar = 1;
});

JavaScript redirect to another page when time reaches 5 minutes to top of hour

I want to redirect a user to another page when the time reaches 5 minutes to the top of the hour.
In 24 hour time that means I want the redirect to run on intervals like this...
11:55
12:55
13:55
14:55
15:55
etc
So far all I can figure out is the "count down" style of JS redirection like this, but instead of that I need something that runs based on time (5 minutes to the top of the hour) not a count down.
setTimeout("location.href = 'https://www.google.com';",1000);
I have also tried this but nothing happened.
var mins = new Date().getMinutes();
if (mins == 55) {
window.location.href = "https://www.google.com";
}
Is this possible with JavaScript (or jQuery)?
You're close - you just need to calculate the time remaining from when the user loads the page. I would throw this in the document.ready callback if you're already using jQuery.
const interval = 55*60*1000 // 55 min in ms
const msUntilNext = interval - new Date().getTime() % interval;
const timeout = setTimeout(() => {
location.href = 'https://www.google.com';
}, msUntilNext)
setTimeout() happens after a specified amount of time, where you have it defined to fire after 1 second (1000 milliseconds = 1 second) and then it will stop, unless you trigger the timeout again.
One solution is to check the timeout every 1 second using setInterval, and as soon as the minutes reach 55 minutes, do the redirect. You could also change this to trigger less frequently, say every 15 or 30 seconds (15000, 30000).
// function that triggers at the interval
function checkTimeout() {
var now = new Date();
var minutes = now.getMinutes();
console.log(minutes);
if (minutes >= 55) {
location.href = 'https://www.google.com';
}
}
setInterval(checkTimeout, 1000); // check interval every 1 second

Javascript setInterval function clock dependent instead of load dependent

Is it possible to start setInterval counter clock dependent instead of load dependent?
Assuming that every computer has the minutes of the clock always at the same time.
If I open the page at 12:01 and I want a set interval of 2 minutes that always start from 12:00 (or any other hour but at :00 minutes). I want the event to fire at 12:02, 12:04 etc. no matter when I load the page or if it was open or not at 12:00.
The answer can be in jquery too.
You could take the delta to the next wanted slot and adjust with it the timeout.
function out(k, v) {
console.log(k.toString().padEnd(8), v.toString().padStart(15));
}
var time0 = new Date().getTime(),
slot = 2 * 60 * 1000,
time1 = Math.floor(time0 / slot + 1) * slot,
delta = time1 - time0;
out('slot', slot);
out('delta', delta);
out('time0', time0);
out('time1', time1);
setTimeout(function () {
var time2 = new Date;
out('time2', time2.getTime());
out('real', time2.getTime() - time0);
console.log(time2.toISOString());
}, delta);

A repeating countdown timer that continues even after browser refresh

Firstly I am very new to javascript. I have a Shopify store and I am planning to have a countdown timer just like Amazon to each of my product pages. I know there are a lot of plugins I can use for Shopify but none of them matches with the theme and style of my Shopify store so I planned to make one myself.
What I want is if User-1 opens my website and navigates to a product page, he should see a timer counting down to a specific time say 12:00:00 (hh:mm:ss). Suppose User-1 sees 'Deal ends in 11:20:10' Now if User-2 opens the same product page at the same time then he should also see 'Deal ends in 11:20:10' The whole point is the timer should not refresh back to 12:00:00 every time the browser loads/reloads the page and every user on the website should see the same time remaining on the countdown timer.
I starting with a bit of research and managed to run a timer on my store. It's not exactly what I want but here's the code:
var interval;
var minutes = 1;
var seconds = 5;
window.onload = function() {
countdown('countdown');
}
function countdown(element) {
interval = setInterval(function() {
var el = document.getElementById(element);
if(seconds == 0) {
if(minutes == 0) {
el.innerHTML = "countdown's over!";
clearInterval(interval);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? 'seconds' : 'second';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + ' remaining';
seconds--;
}, 1000);
}
</script>
And here's what it looks like:
It does work but has the following problems:
It refreshes with the browser refresh.
It doesn't have hours.
It does not auto-repeat when the timer reaches zero.
For every user time remaining varies.
As I mentioned I am almost a noob in JavaScript. Can anyone help me build a countdown timer that overcomes the above issues?
Explanation
Problem 1: It refreshes with the browser refresh.
Cause: Because you hardcoded the seconds and minutes (var seconds = 5, var minutes = 1), every user that visits the page will see the timer counting down from the exact same value being "1 minute and 5 seconds remaining" again and again.
Solution: Instead of hardcoding the start value of the countdown, hardcode the deadline. So instead of saying to each visitor of your page "Start counting down from 1 min and 5 sec to 0!", you have to say something like "Count down from whatever time it is now to midnight!". This way, the countdown will always be synced across different users of your website (assuming that their computer clock is set correctly).
Problem 2: It doesn't have hours.
Cause: Your code has only variables to keep track of seconds and minutes, there is no code written to keep track of the hours.
Solution: Like proposed in the solution for problem 1: don't keep track of the hours/minutes/seconds remaining, but only keep track of the deadline and then calculate hours/minutes/seconds remaining based on the current client time.
Problem 3: It does not auto-repeat when the timer reaches zero.
Cause: The nested ifs (that check seconds == 0 and m == 0) in your code explicitly state to display the text "countdown's over!" when the countdown is over.
Solution: Keep a conditional that checks when the countdown is over but instead of displaying "countdown's over!", reset the deadline to a next deadline.
Problem 4: For every user time remaining varies.
Cause: See Problem 1
Solution: See Problem 1
Sample code
here is a piece of code that integrates the solutions mentioned above:
const span = document.getElementById('countdown')
const deadline = new Date
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)
function displayRemainingTime() {
if (deadline < new Date) deadline.setDate(deadline.getDate() + 1)
const remainingTime = deadline - new Date
const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
const seconds = extract( 60000, 1000 )
const minutes = extract( 3600000, 60000 )
const hours = extract(86400000, 3600000)
const string = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}
window.setInterval(displayRemainingTime, 1000)
displayRemainingTime()
<h3>
<span id="countdown"></span>
</h3>
Edit: make sure the client time is correct
If you don't trust your clients for having their time set up correctly. You can also send a correct timestamp from the server that serves your page. Since I don't know what kind of server you are using I can't give an example for your server code. But basically you need to replace the code (from the following example) after const trustedTimestamp = (being (new Date).getTime()) with a correct timestamp that you generate on the server. For the correct formatting of this timestamp refer to Date.prototype.getTime()
const span = document.getElementById('countdown')
const trustedTimestamp = (new Date).getTime()
let timeDrift = trustedTimestamp - (new Date)
const now = () => new Date(timeDrift + (new Date).getTime())
const deadline = now()
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)
function displayRemainingTime() {
if (deadline < now()) deadline.setDate(deadline.getDate() + 1)
const remainingTime = deadline - now()
const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
const seconds = extract( 60000, 1000 )
const minutes = extract( 3600000, 60000 )
const hours = extract(86400000, 3600000)
span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}
window.setInterval(displayRemainingTime, 1000)
displayRemainingTime()
<h3>
<span id="countdown"></span>
</h3>
Time from google server
To create a working example I added this experiment where I get the correct time from a Google page. Do not use this code on your website because it is not guaranteed that google will keep hosting this web-page forever.
const span = document.getElementById('countdown')
const trustedTimestamp = (new Date).getTime()
let timeDrift = 0
const now = () => new Date(timeDrift + (new Date).getTime())
const deadline = now()
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)
window.setInterval(displayRemainingTime, 1000)
window.setInterval(syncClock, 3000)
displayRemainingTime()
syncClock()
function displayRemainingTime() {
if (deadline < now()) deadline.setDate(deadline.getDate() + 1)
const remainingTime = deadline - now()
const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
const seconds = extract( 60000, 1000 )
const minutes = extract( 3600000, 60000 )
const hours = extract(86400000, 3600000)
span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}
function syncClock() {
const xmlhttp = new XMLHttpRequest();
xmlhttp.open("HEAD", "http://www.googleapis.com",true);
xmlhttp.onreadystatechange = function() {
const referenceTime = new Date
if (xmlhttp.readyState==4) {
const correctTime = new Date(xmlhttp.getResponseHeader("Date"))
timeDrift = correctTime - referenceTime
}
}
xmlhttp.send(null);
}
<h3>
<span id="countdown"></span>
</h3>
I am not sure how Shopify handles plugins, but there must be some way to edit CSS for them, so you could have them match the style of your theme.
What you've done here, in the JS you've provided, will always have that behavior because it is client-side code. The script will run after each refresh, and will always refresh the values minutes and seconds to the associated initial values namely 1 and 5. I believe this answers your first question.
As per your second question, you clearly have not coded hours in that JS script. So hours should not appear, it would be a mystery if they did!
With respect to your third question, you only call countdown once during the onload function.
And by the first answer, it is natural that the clock should not be synchronized among users since they would logically be refreshing your page at different times.
So I think your best bet is to use one of the plugins and just modify the CSS.

Categories