Start a function at a specified date - javascript

I m working on a TV player on raspberry pi/raspbian
The player part work, my playlist work too, but I m stuck at this:
I get the playlist with a start date (parsing is ok), but I have no idea how I could do to replace the previous playlist by the new one at the scheduled date.
Is there a way to start a function only at a specified time without eating all the cpu by a false "wait"?
I was wondering about setTimeOut function, but is there better way than this?

Take a look at node-cron. It will make a call to your callback at the specified cron time. Take a look at some sample code:
var cronJob = require('cron').CronJob;
new cronJob('00 30 11 * * 1-5', function(){
// Runs every weekday (Monday through Friday)
// at 11:30:00 AM. It does not run on Saturday
// or Sunday.
console.log('Hello');
}, null, true, "America/Los_Angeles");

Related

How to shift fullcalendar's display time by several minutes

This could be an embarrassingly easy question but I am new to Moment.js and fullcalendar.
The goal: Get fullcalendar to operate on a Moment/DateTime that is a few minutes offset from local computer time.
The rationale:
We want to synchronize the display time and nowIndicator with the old clocks in a building as opposed to the desktop's time.
Tried so far:
// Get current offset:
var localOffset = moment().utcOffset();
// Shift by 7 minutes for illustration
localOffset -= 7;
// Set new offset for moment
moment().utcOffset(localOffset);
alert(moment().utcOffset());
As of now it prints back the original UTC offset and the nowIndicator matches my system clock. This is using Moment.js 2.19.0.
Thanks for looking.
moment().utcOffset() is creating a new moment with the default offset. It has nothing to do with the object you previously set an offset on. momentJS works using individual objects which are instantiated by using the moment() constructor. It's not a static or global thing.
What you need to do is work with the moment object which you set the offset on:
var offsetMoment = moment();
offsetMoment.utcOffset(localOffset);
alert(offsetMoment.utcOffset());
ADyson's answer cleared the misconception about a moment object and its scope.
To answer the original problem of shifting FullCalendar's time by an arbitrary amount, use the 'now' option when initializing:
// Get current time as moment object and add 7 minute offset
var shiftedTime = moment().add(7, 'minutes');
// Set 'now' option in calendar initialization to new moment object
$('#calendar').fullCalendar({
// put your options and callbacks here
now: shiftedTime,
defaultView: 'agendaDay',
nowIndicator: true
});
The display of the calendar and the now indicator will be shifted 7 minutes relative to local machine time.

Recurring function to reset variable/counter at midnight (moment.js, node.js)

I want to reset a variable during midnight. Every night.
I'm trying to build this function with Moment.js for Node but I can't seem to get the recurring part to work properly.
This is what I got so far.
// Calculate time to midnight
function timeToMidnight(){
var midnight = new Date();
midnight.setHours(0,0,0,0);
var now = new Date();
var msToMidnight = midnight - now;
console.log(' it is ' + msToMidnight + 'ms until midnight');
return msToMidnight;
};
// Reset counter at midnight
setTimeout(function(){
console.log("midnight, do something");
}, timeToMidnight());
How can I best make it recurring at midnight, every night?
Thanks in advance.
If you're using moment, consider instead this implementation
var moment = require('moment');
function timeToMidnight() {
var now = new Date();
var end = moment().endOf("day");
return end - now + 1000;
}
Like your function, this takes now milliseconds and calculates the number of milliseconds until midnight, but this is supported directly when using moment, which is nice. Add 1 extra second (1000 milliseconds) to get to the next day.
A typical pattern is for a function to call itself after a timeout.
function roundMidnight() {
console.log('at midnight');
setTimeout(roundMidnight,timeToMidnight());
}
setTimeout(roundMidnight,timeToMidnight());
Pretty generic, in fact depending on the value returned, you could schedule anything anytime, pretty useful, seem like someone must have thought of that.
node-schedule
A cron-like and not-cron-like job scheduler for Node.
And they did. Maybe what you really want is node-schedule. It looks like it's not really actively developed now, though.

can setInterval drift over time?

I have 2 node.js webservers. I cache data inside webservers. I sync the cache load/clear based on system time. I have done time sync of all my hosts.
Now I clear cache every 15 mins using following code:
millisTillNexthour = "Calculate millis remaining until next hour"
setTimeout(function() {
setInterval(function() {
cache.clear();
}, 60000*15);
}, millisTillNexthour);
My expectation is even if this process runs for ever, cache will be cleared every 15th minute of each hour of the day.
My question is: can setInterval drift over time?
For eg: right now it clears cache at 10:00 10:15 10:30 10:45 11:00 ......
Can it happen that instead of 10:15 system time, setInterval gets executed at 10:20 system time when it was supposed to clear cache at 10:15??
I am not sure how this works. Please shed some light. I hope I explained my question well.
I'm probably more than a bit late to the party here, but this is how I solved this particular time-slipping problem just now, using a recursively called setTimeout() function instead of using setInterval().
var interval = 5000;
var adjustedInterval = interval;
var expectedCycleTime = 0;
function runAtInterval(){
// get timestamp at very start of function call
var now = Date.now();
// log with time to show interval
console.log(new Date().toISOString().replace(/T/, ' ').replace(/Z/, '') + " runAtInterval()");
// set next expectedCycleTime and adjustedInterval
if (expectedCycleTime == 0){
expectedCycleTime = now + interval;
}
else {
adjustedInterval = interval - (now - expectedCycleTime);
expectedCycleTime += interval;
}
// function calls itself after delay of adjustedInterval
setTimeout(function () {
runAtInterval();
}, adjustedInterval);
}
On each iteration, the function checks the actual execution time against the previously calculated expected time, and then deducts the difference from 'interval' to produce 'adjustedInterval'. This difference may be positive or negative, and the results show that actual execution times tend to oscillate around the 'true' value +/- ~5ms.
Either way, if you've got a task that is executing once a minute, and you run it for an entire day, using this function you can expect that - for the entire day - every single hour will have had 60 iterations happen. You won't have that occasional hour where you only got 59 results because eventually an entire minute had slipped.
setInterval is definitely drifting (although I agree that it should not be). I'm running a Node.js server with an interval of 30 seconds. On each tick, a few async web requests are made which from beginning to end take roughly 1 second. No other user-level/application processing happens in the intervening 29 seconds.
However, I notice from my server logs that over the course of 30 minutes, a drift of 100ms occurs. Of course, the underlying operating system is not to blame for the drift and it can only be some defect of Node.js's design or implementation.
I am very disappointed to notice that there is a bug in the NodeJS implementation of setInterval. Please take a look at here:
https://github.com/nodejs/node/issues/7346#issuecomment-300432730
You can use Date() object to set specific time and then add a certain number of milliseconds to the date.
It definitly can because of how Javascript works (See Event Loop)
Javascript event loop executes the setInterval queue when other queued events are finished. These events will take some time and it will effect your setInterval function's execute time and it will eventually drift away as time passes.
setInterval should not drift in a perfect world. It might be delayed due to other things taking up system resources. If you need a more precise solution to what you have, use the clock() function to " calibrate " your nodes.

jQuery Countdown - Daily Countdown, with secondary countdown as well?

1. Daily Countdown
I'm trying to use Keith Wood's jQuery countdown plugin (http://keith-wood.name/countdownRef.html) in order to create a page of daily countdowns. E.g.:
A - counts down to 07:00 each day
B - counts down to 09:00 each day
C - counts down to 11:00 each day
I'm doing in a fairly hacky way:
var foo = new Date();
foo.setHours(11)
foo.setMinutes(0)
foo.setSeconds(0)
$('#fooCountdown').countdown({until: foo});
Basically, I just create a new Date object which defaults to now, then set the time to the time I want for today.
However, this is pretty hacky, and also it doesn't reset at the end of the day - once the new day ticks over, it's still counting down to the time on the previous day.
Is there a cleaner or better way of doing daily countdowns with this plugin?
2. Secondary Countdown
Secondly - I also want each countdown, when it expires, to count down to a second later time that day.
E.g. for A - once it reaches 07:00, it then starts counting down to 15:00 for that day.
I'm doing this using the onExpiry function:
$('#officeCountdown').countdown({until: officeOpens, onExpiry: OfficeOpen, alwaysExpire: true});
...
function OfficeOpen() {
$('#officeCountdown').countdown('option', {until: officeCloses, onExpiry: OfficeClose, alwaysExpire: true});
}
function OfficeClose() {
alert('Office has closed')
}
The first part - counting down down until officeOpen seems to work.
However, the second part - counting down until OfficeClose doesn't - it seems to always start counting down the difference between officeOpens and officeCloses, instead of using the current time - and also, the function OfficeCLose never seems to trigger.
Any thoughts?
I would suggest you use the excellent Datejs plugin for creating/handling dates.
(read the getting-started and the docs because it is really extensive)
This way you could do
$('#fooCountdownA').countdown({
until: Date.today.set({hour:7})
});
$('#fooCountdownB').countdown({
until: Date.today.set({hour:9})
});
$('#fooCountdownC').countdown({
until: Date.today.set({hour:11})
});
As for the countdown, the plugin does not seem to be friendly to re-using countdowns..
Perhaps you are better off creating dummy elements and inserting them in the dom to hold the countdown, and destroying them on expiry..

Javascript countdown and timezone and daylight saving time issues

Our team are having big issues with the JQuery countdown and we really need some help.
Initially, we had some ScriptSharp code that does this
JQueryCountdownOptions opts = new JQueryCountdownOptions();
opts.Layout = "<ul class=\"group\"> <li>{dn} <span>{dl}</span></li> <li>{hn} <span>{hl}</span></li> <li>{mn} <span>{ml}</span></li> <li>{sn} <span>{sl}</span></li> </ul>";
opts.Until = Number.ParseInt(timeLeft);
jQuery.Select("#countdownclock").Plugin<JQueryCountdown>().Countdown(opts);
jQuery.Select("#countdownclock").Show();
jQuery.Select("#bidBox").RemoveAttr("disabled");
What we noticed is that this uses the client's clock to countdown from. So, if the client decided to change his time to 5 hours ahead then the countdown would be 5 hours off.
To fix this we introduced some more code
In the view:
$(function () {
var expires = new Date(#year, #month, #day, #hours, #minutes, #seconds);
$('#clockDiv').countdown({ until: expires, timeZone: null, serverSync: serverTime, onTick: serverTime, tickInterval: 60 });
function serverTime() {
var time = null;
$.ajax({ url: '/Auction/SyncServerTime',
async: false, dataType: 'json',
success: function (result) {
time = new Date(result.serverTime);
}, error: function (http, message, exc) {
time = new Date();
}
});
return time;
}
});
In the controller
public JsonResult SyncServerTime()
{
var result = new JsonResult
{
Data = new
{
serverTime = DateTime.Now.ToString("MMM dd, yyyy HH:mm:ss zz")
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return result;
}
This code ensures that no matter what the user sets his clock to the countdown timer will periodically sync to the server's time. Problem solved.
The only issue is that we have come up with other issues.
The problem is that when users are in different timezones then the countdowns of those users are different depending on the timezone offset that their timezone has. We have tried changing all sorts of parameters and still are having issues. To make matters worse if my timespan straddles a date when daylight saving time is applied then things go awry again, both for those in the same timezone and those in different ones. We have experimented with different code and parameters so the above is just what I did and is different from what my esteemed colleagues tried. What I am asking is surely, someone somewhere out there must have had a requirement to
Write a countdown that is independent of client time and based on server time.
Shows the same number of days, hours, minutes, seconds remaining no matter what timezone a user is in
Shows the same number of days, hours, minutes, seconds remaining for a user whose time will change in this period because of DST to user whose time will not change in this period because of DST
Shows the actual number of days, hours, minutes and seconds remaining for a user whose time will change in this period because of DST.
We cannot be the only people who have ever had this issue, surely. It cannot be this hard. Does anyone know a solution?
Thanks,
Sachin
I haven't dealt with the same scenarios personally, but seeing Date, timezone issues etc. pop up automatically triggers thoughts about some potential issues stemming from the use of local date objects as opposed to UTC date objects.
IMO, things are simply better off if all computation, serialization of dates only worked in the UTC space, and finally when it comes to present a date from a user, it is converted to local or appropriate time zone depending on the scenario. On the flip-side, the user enters local or some time zone relative entry, and immediately that is converted to UTC as the internal representation. This avoids all sorts of confusion across different layers/tiers of the app.
Its not really a solution to your specific problem, but perhaps something to consider that could lead to one.

Categories

Resources