How can I run my node js script automatically using scheduler - javascript

I have created a nodejs file.
Currently i need to schedule the task to run that file automatically at multiple occasion in a single day.
var schedule = require('node-schedule');
var rule = new schedule.RecurrenceRule();
rule.hour = 12;
var j = schedule.scheduleJob(rule, function(){
console.log('Hello world!');
});

The documentation say date and not day
RecurrenceRule properties:
second
minute
hour
date
month
year
dayOfWeek
https://github.com/node-schedule/node-schedule

For starters, you need to set the date, not the day, but either way, setting the date = 1 doesn't make the time interval equal 1 day, it makes the date that this rule occurs on equal to 1. In this case, because the week starts on sunday and it begins at 0, you set the rule to occur every Monday at midnight.
For the scheduler, everything defaults to 0 unless you set it. Because you set the rule.date = 1, everything else, the minute, hour, etc all =0.
If you want it to occur every day, you would need to set a range of days:
rule.dayOfWeek = [new schedule.Range(0, 6)];
Then you would need to set the time that this occurs at. For example, if you wanted it to occur at 10:30 am, you would set:
rule.minute = 30
rule.hour = 10

You should use this
var j = schedule.scheduleJob('0 0 0 * * *', function(){
console.log('for 12:00 am daily' );
});
and for particular time use this
0 30 8 * * *
8:30 am

Related

How to make a time* range include upper bound

I've divided a day into 8 ticks of three hours each. When making this range it goes from 00:00 to 21:00, and not until 00:00 again.
const startDate = new Date("2021-03-14T23:00:00.000Z");
const endDate = new Date("2021-03-15T23:00:00.000Z");
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, endDate);
dayInThreeHourPeriods.forEach((period) => {
console.log(`period: ${format(period, 'HH:mm')}`);
});
// outputs
// from: 00:00
// to: 21:00
// would like it to go to 24:00
How can I change this so that it goes to 24:00?
I want to use it for an axis:
Made a working example here: https://jsfiddle.net/Spindle/kfL5oh12/21/
This is intended from the .range method, as d3.timeHour.every is just an alias to interval.range;
From d3-time docs:
interval.range(start, stop[, step]) ยท Source
Returns an array of dates representing every interval boundary after or equal to start (inclusive) and before stop (exclusive). If step is specified, then every stepth boundary will be returned; for example, for the d3.timeDay interval a step of 2 will return every other day. If step is not an integer, it is floored.
As you've already stated in your own answer, it seems like a known issue.
Anyway, why don't use write your own logic to divide the day into 3-hours chunks? This way we don't need to rely on d3d3's .range method;
let startDate = new Date("2021-03-14T23:00:00.000Z");
let endDate = new Date("2021-03-15T23:00:00.000Z");
var dayInThreeHourPeriods = [ startDate ];
while (endDate > startDate) {
startDate = new Date(startDate.getTime() + (60 * 60 * 3 * 1000));
dayInThreeHourPeriods.push(startDate);
}
console.log(dayInThreeHourPeriods);
Updated JSFiddle
Turns out this is a known issue.
What people tend to do is add a small time period and suddenly it's inclusive:
d3.range(min, max+0.001)
or in my case:
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, d3.timeHour.offset(endDate, 1));
Not ideal. Look there's a proposal to have 'rangeInclusive' which would be better already. But there is no activity on that issue.
If anyone has a better idea for the time being I'd be interested.

Each day a different item in an array - javascript

I have this script that makes a button redirect to a whatsapp page, on the URL (a href) I need to insert the number that's gonna be contacted.
What I need to do is each day a different number fills this URL.
Example:
day1 - phonen1,
day2 - phonen2,
...,
day 13 - phonen13,
//(starts over)
day14 - phonen1,
day15 - phonen2,
...
<a id="whatsapp" target="_blank" href="https://api.whatsapp.com/send?phone=5519997820734">Link</a>
<script>
phones= ["phonen1", "phonen2", ..., "phonen13"];
document.getElementById("whatsapp").href = "https://api.whatsapp.com/send?phone=5519"+ phones[i] +"";
</script>
you can use the date object with for loop like this:
<a id="whatsapp" target="_blank" href="https://api.whatsapp.com/send?phone=5519997820734">Link</a>
<script>
phones= ["phonen1", "phonen2", ..., "phonen13"];
var d = new Date();
var todayDate = d.getDate();
for (var i = todayDate; i > 13; i= i-13) {
todayDate = todayDate - 13;
}
document.getElementById("whatsapp").href = "https://api.whatsapp.com/send?phone=5519"+phones[i] + todayDate;
</script>
Simple Answer:
You can do this using a Date to count the number of days since the unix epoch, and mod that count by the length of your phones array to get an index that moves to the next item every 24 hours:
let phones = ["phonen1", "phonen2", "phonen3", "phonen4"];
const ms_per_day = 24 * 60 * 60 * 1000;
// (new Date()).getTime() gets the number of ms since 1 January 1970 00:00:00 UTC
// we divide by ms_per_day and floor to get the number of 24-hour cycles (this will increment each UTC day)
let days_since_epoch = Math.floor((new Date()).getTime() / ms_per_day);
// we mod by the length of phones to get a number in the range [0, phones.length)
let phones_index = days_since_epoch % phones.length;
document.getElementById("whatsapp").href = "https://api.whatsapp.com/send?phone=5519" + phones[phones_index];
console.log("Set link to", document.getElementById("whatsapp").href);
<a id="whatsapp" target="_blank" href="https://api.whatsapp.com/send?phone=5519997820734"> Link </a>
Caveats:
Working with time is complicated. The above method doesn't get the number of days exactly:
Due to the differing lengths of days (due to daylight saving changeover), months and years, expressing elapsed time in units greater than hours, minutes and seconds requires addressing a number of issues and should be thoroughly researched before being attempted.
...and the crossover time is in UTC anyway, so it's non-obvious when the above code will switch numbers (it won't be at midnight). But it will do so once every 24 hours, which should be sufficient for the use case described in the post.
One other caveat is that the number won't actually change until the user refreshes the page and reruns the script.
Use the date object to create an index into your array
<a id="whatsapp" target="_blank" href="https://api.whatsapp.com/send?phone=5519997820734">Link</a>
<script>
var phones= ["phone1","phone2","phone3","phone4","phone5","phone6","phone7","phone8","phone9","phone10","phone11","phone12","phone13","phone14"];
var startOfDay1 = new Date('July 1, 2018 00:00:00');//be aware this is the client timezone
var diffFromNow = Date.now() - startOfDay1.getTime();//get the difference in ms between now and midnight of "day 1"
console.log(diffFromNow);
var diffFromNowDays = diffFromNow/(24*60*60*1000);//turn that into a day value
var daynum = Math.floor(diffFromNowDays % 14);//constrain to 14 days
console.log(daynum);//zero based index
document.getElementById("whatsapp").href = "https://api.whatsapp.com/send?phone=5519"+ phones[daynum] +"";
</script>
Ollin's answer is great, but you can use local midnight as follows if you wish. Use the remainder operator % with the number of whole days since a particular point in time, any epoch will do.
If you want to do the changeover at midnight local time, then use local midnight for the epoch and current day. Use Math.round to remove daylight saving effects.
The following will change the value returned from the array at local 00:00:00.001 each day:
// Number of whole local days since date to today
function daysDiff(date) {
// Copy date, set to start of day
var d = new Date(+date);
d.setHours(0,0,0,0);
// Get start of current day
var e = new Date();
e.setHours(0,0,0,0);
// Return whole day count
return Math.round((e - d)/8.64e7);
}
// Select item from array based on number of whole days
// from epoch to today. Default is 1 July 2018
function getFromArray(array, epoch) {
if (!epoch) {
// If not provided, use 1 July 2018
epoch = new Date(2018,6,1);
}
var d = daysDiff(epoch);
return array[d % array.length];
}
var nums = [1,2,3,4,5,6,7,8,9,10,11,12,13,14];
// On local date 12 July 2018 returns 12
console.log(getFromArray(nums));

Momentjs / Angularjs - Checking if 2 dates are in the same period - TimeSheet project

I am working on a simple Timesheet app, I am trying to implement an auto calculator that will sum up your hours for each day (Sunday, Monday, Tuesday, etc ...). A problem I noticed is that in some cases, users will enter activities that will be within the same date time periods.
For example:
$scope.Example = [
{Description:"Example activity",Start:"2018-06-24 8:00",End:"2018-06-24 10:00",Total:2},
{Description:"Example activity2",Start:"2018-06-24 9:00",End:"2018-06-24 10:00",Total:1},
{Description:"Example activity3",Start:"2018-06-24 10:00",End:"2018-06-24 11:00",Total:1}];
$scope.Calculate_all_entries = function(){
$scope.Total.Sunday = 0;
if($scope.Example){
angular.forEach($scope.Example, function(element){
if(moment(element.Start).format("dddd") === "Sunday"){
$scope.Total.Sunday = $scope.Total.Sunday + element.Total;
}
})
}
}
In this case the total should be 3 hours and not 4 hours as we dont charge for work within the same hours. I'm need to implement a system that would check if the dates are within the same period and provide the appropriate total.
I found this in the documentation on momentjs that seemed to be close to what i need but only takes one value:
moment('2010-10-19 11:00').isBetween('2010-10-19 10:00', '2010-10-25 00:00'); // true
Would anyone know of any other methods to check wether or not the start and end time are in the same period as other entries in the same day?
Sure, you can use momentjs's unix() function to convert those date times to an integer which then can easily be used to check whether the timestamp is in between two other timestamps.
Here is an example:
var timeToCheck = moment('2010-10-19 11:00').unix();
var startTime = moment('2010-10-19 10:00').unix();
var endTime = moment('2010-10-25 00:00').unix();
console.log(timeToCheck >= startTime && timeToCheck <= endTime); // true

Ability to select time after midnight

I've opening and closing hours select drop-down. This is basically to select opening and closing hours of a shop. I've created the list of hours with 15 min interval from 12:00 Morning to 12:00 Midnight.
$scope.availableTimes = [];
$scope.availableTimes.push({
'msValue': 0,
'display': '12:00 Morning'
});
for (var msValue = 900000; msValue <= 85500000; msValue += 900000) { // 90.000ms = 15 min, 85.500.000ms = 11:45PM
$scope.availableTimes.push({
'msValue': msValue,
'display': moment(msValue).utc().format("h:mm A")
})
}
var dayMS = 86400000 - 1;
$scope.availableTimes.push({
'msValue': dayMS,
'display': '12:00 Midnight'
});
But there might be some case they want to select the
Opening hour : 11:00am & Closing hour: 2:00am (after midnight) total 15 hours.
To handle this situation visually I made a workaround. I rearrange the closing hours based on the opening hour selection.
Example:
If opening hour selected as 11:00 am, available closing hours will start from 11:15 am upto 10:45 am.
Here the directive to make closing hours list:
app.directive('closingTimeSync',function(){
return {
template: `<div class="col-xs-6">
<div class="form-group">
<label for="exampleFormControlSelect1">Closing Hours</label>
<select class="form-control" data-ng-options="time.display for time in closingTimes" data-ng-model="selectedToTime">
</select>
</div>
</div>`,
replace: true,
transclude: true,
link: function(scope) {
scope.automaticallySelectClosingTime = function(msValue) {
scope.closingTimes = scope.availableTimes;
var dayMS = 86400000 - 1;
var remainingTimings = [];
var index = scope.closingTimes.map(function(obj){return obj.msValue;}).indexOf(msValue);
index = (index === scope.availableTimes.length-1) ? 1 : index+1;
scope.closingTimes = scope.closingTimes.slice(index,scope.availableTimes.length);
if(msValue !== dayMS) {
remainingTimings = scope.availableTimes.slice(1,index -1);
}
scope.closingTimes = scope.closingTimes.concat(remainingTimings);
scope.selectedToTime = scope.closingTimes[0];
};
}
};
});
Plunker
Problem:
You can see I'm just adding remainingTimings = scope.availableTimes.slice(1,index -1);. It gives the ability to select a time after midnight but technically in the millisecond level 2:00 am is less than 11:00 am.
How can I add one extra day in milliseconds if someone selects anything after 12:00 midnight?
Hope I was able to explain clearly.
Simply add 24 Hours if the closing time is lower than your opening time
I would not create lists.
The first list can just be written into the HTML directly, since it will never change.
Or you could create it with a simple angular loop instead of a scope lookup.
Every day starts at 00:00 and ends at 23:59
The second list is just the first list + the amount of time the store is open. And you know that in advance. ( 15 hours )
So I would go for something like this:
<select>
<option value="00:00">00:00</option>
<option value="00:15">00:15</option>
<!-- add more options -->
<option value="23:45">23:45</option>
</select>
And for the event handler:
function( event ) {
// Get the selected value in the dropdown.
const time_chunks = event.target.value.split( ':' );
// Get the current datetime.
const opening = new Date();
// Set the current datetimes hours and minutes to the selected value so opening equals todays opening time.
opening.setHours( time_chunks[ 0 ] );
opening.setMinutes( time_chunks[ 1 ] );
// 3600000 miliseconds = 1 hour
const hours_open = 15;
const ms_open = hours_open * 3600000;
const closing = new Date( opening.getTime() + ms_open );
// Add code to transform the datetime into the label you need.
// Add code to save the current state in $scope if needed.
// Add code to select the correct option in the second dropdown.
}
You can probably rewrite the same logic with actual angular and moment methods.
By using actual dates instead of trying to recreate timestamps in a list, you avoid all kinds of timestamp issues like daylight savings time, month barriers on the last day of a month, year barriers on 31 december, etc.
You can use the same principle to generate the lists, if for example, the closing hours don't always have to be 15 hours, the point is, do all calculations with full datetimes instead of only the times part so the date will actually change to the next day if the closing time is next day

How does weekly reminders work?

Is there an algorithm for weekly reminders ?
For example, I set a reminder for Thursday & I check the "weekly" option.
The Reminder is supposed to alert every Thursday then,but how is this done?
I thought about an idea, but I guess it's very stupid:
Get today's "day".
Get today's "date".
Get the wanted day number.
Subtract both days from each other.
using [4] get that day's date.
Increment the counter after every alert with 7.
I don't even know whether this will work or not, I'm sure there is a better way to do it, so I need your opinions before starting implementation.
PS: I use JavaScript so the functions are very limited.
It's not entirely clear what you're trying to do.
If your code needs to know whether it's Thursday, that's really easy using getDay, which gives you the day of the week:
if (new Date().getDay() === 4) {
// It's Thursday
}
The day numbers start with 0 = Sunday.
If your code needs to find the next Thursday starting on a given date:
var dt = /* ...the start date... */;
while (dt.getDay() !== 4) {
dt.setTime(dt.getTime() + 86400000)) // 86400000 = 1 day in milliseconds
}
or of course without the loop:
var dt = /* ...the start date... */;
var days = 4 - dt.getDay();
if (days < 0) {
days += 7;
}
dt.setTime(dt.getTime() + (days * 86400000));
If you have a Thursday already and you need to know the date for the next Thursday:
var nextThursday = new Date(thisThursday.getTime() + (86400000 * 7));

Categories

Resources