I am trying to find the best approach to comparing date/times using Javascript in order to prevent double booking on a SharePoint calendar. So I load an array with items that contain each event, including their start date/time and end date/time. I want to compare the start date/time and end date/time against the start/end date/times in the object, but I am not sure how to ensure that dates will not lapse.
like:
//date that is created from user controls
var startDate = new Date(startDat + 'T' + startHour + ':' + startMin + ':00');
var endDate = new Date(endDat+ 'T' + endHour+ ':' + endMin+ ':00');
for ( var i = 0; i < allEvents.length; i++ ) {
var thisEvent = allevents[i];
//having trouble with the compare
//i have tried silly ifs like
if (thisEvent.startDate >= startDate && thisEvent.endDate <= endDate) {
// this seems like I am going down the wrong path for sure
}
}
I then tried breaking apart the loaded object into seperate values (int) for each component of the date
var thisObj = { startMonth: returnMonth(startDate), startDay: returnDay(startDate), etc
but I am not sure this isn't just another silly approach and there is another that just makes more sense as I am just learning this.
I have a similar requirement in progress but chose to solve it at the booking stage, with jQuery/SPServices.
The code is still in build (ie not finished) but the method may help.
I attach an event handler to a column, then on selection, fetch all the dates booked in the same list to an array, then display that array on a rolling 12 month cal, as below.
I'm not checking to ensure a new booking doesn't overlap but a quick scan through the array on Pre-Save would provide a strict Go/No Go option for me. Relies on client side JS though, so not going to work in a datasheet or web services context.
Related
I have created a small function which give all dates between two dates.
but this is starting from Plus 1 date.
Here's my code (also on Here is jsfiddle):
function DateRangeArr(to, from) {
console.log(to);
console.log(from);
var Dateresult = [];
var end = new Date(from);
var loop = new Date(to);
while (loop <= end) {
Dateresult.push({ 'total': 0, 'log_date': loop });
var newDate = loop.setDate(loop.getUTCDate() + 1);
loop = new Date(newDate);
}
return Dateresult;
}
console.log(DateRangeArr('2020-12-05','2020-12-12'));
It's giving me results starting from 2020-12-06 to 2020-12-13. Also will it gives result depending upon user time zone ?
There are a couple of things going on that could account for the problem.
(This is probably the thing you're seeing) You're changing the state of the Date instance that you added to the array after adding it. That changes the instance that's in the array.
Since "2020-12-05" is a date-only string, it's parsed as UTC in specification-compliant browsers (see the rules at Date.parse), so the Date objects will represent midnight on that date UTC rather than midnight on that date in your local timezone. If you want them to reliably be midnight local time, add T00:00 to the string. If you want them to be parsed reliably as UTC, you should be able to use them as-is, but the spec moved around on this (ES2015 said they should be parsed as local time, not UTC, before being updated by ES2016) so to get UTC reliably, add T00:00Z to it. (My understanding is that the spec allows just adding a Z, but others read the spec differently, and both Safari's JavaScriptCore and Firefox's SpiderMonkey reject new Date("2020-12-05Z"), so add T00:00Z.) Or use new Date(Date.UTC(year, month - 1, day)) instead.
You're mixing up accessors here: loop.setDate(loop.getUTCDate() + 1). That's using the UTC accessor to get the date, but then the local time accessor to set it. You need to be consistent in order to add a day to the date.
You haven't said how you're using the resulting array of Date objects, but just note that the date they show may seem off if (for instance) you parse them as UTC but then display the result in local time or vice-versa, because of the time zone offset.
You have to and from reversed in your code. You're using them consistently, but it's quite hard to read. :-) When building an array in date order, it goes from the earlier date to the later date.
Here's a version updated to work entirely in UTC; the resulting Date objects represent midnight UTC on each of the dates:
function dateRangeArr(from, to) {
console.log(from);
console.log(to);
var dates = [];
var end = new Date(to + "T00:00Z");
var loop = new Date(from + "T00:00Z");
while (loop <= end) {
dates.push({ "total": 0, "log_date": new Date(+loop) });
loop.setUTCDate(loop.getUTCDate() + 1);
}
return dates;
}
console.log(dateRangeArr("2020-12-05","2020-12-12"));
(I've also updated the function and variable names to be more consistent with standard practice in JavaScript, since the function isn't a constructor function.)
Here's a version that works in local time instead:
function dateRangeArr(from, to) {
console.log(from);
console.log(to);
var dates = [];
var end = new Date(to + "T00:00");
var loop = new Date(from + "T00:00");
while (loop <= end) {
dates.push({ "total": 0, "log_date": new Date(+loop) });
loop.setDate(loop.getDate() + 1);
}
return dates;
}
console.log(dateRangeArr("2020-12-05","2020-12-12"));
Which you use depends on whether you want the Date instances to represent midnight UTC (use the UTC version) or midnight local time (use the local time version).
I am trying to build a graph based on BTC historical price data from coinbase.
Part of this requires that I make the data retrieved from coinbase usable for chart js.
I am having trouble with this aspect.
function getBitcoinHistory(){
$.ajax({
url: "https://api.coindesk.com/v1/bpi/historical/close.json",
success: function(historicalPrice){
console.log(JSON.parse(historicalPrice))
var dateArray = []
dateToday = year+"-"+month+"-"+day
dataStartDate = year+"-"+month-1+"-"+day-1
console.log("month is "+month+" day is "+day)
//set up month and day first
dataMonth=month-1
dataDay=day-1
console.log("data date starts at 0"+dataMonth+"-"+dataDay)
//loop through all of the dates from oldest to newest
for(var i = 0; i < 31; i++){
//formatting correctly
if(dataMonth<10 && dataDay<10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-0"+(dataMonth)+"-0"+(dataDay+i)]; console.log("2019-0"+(dataMonth)+"-0"+(dataDay+i))}
if(dataMonth<10 && dataDay>=10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-0"+(dataMonth)+"-"+(dataDay+i)]; console.log("2019-0"+(dataMonth)+"-"+(dataDay+i))}
if(dataMonth>=10 && dataDay<10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-"+(dataMonth)+"-0"+(dataDay+i)]; console.log("2019-"+(dataMonth)+"-0"+(dataDay+i))}
if(dataMonth>=10 && dataDay>=10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-"+(dataMonth)+"-"+(dataDay+i)]; console.log("2019-"+(dataMonth)+"-"+(dataDay+i))}
//if the date does not exist then it must be the next month
if(dateArray[i]==undefined){
dataMonth=dataMonth+1
dataDay=1
if(month>12){
month=1
}
if(dataMonth<10 && dataDay<10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-0"+(dataMonth)+"-0"+(dataDay+i)]; console.log("2019-0"+(dataMonth)+"-0"+(dataDay+i))}
if(dataMonth<10 && dataDay>=10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-0"+(dataMonth)+"-"+(dataDay+i)]; console.log("2019-0"+(dataMonth)+"-"+(dataDay+i))}
if(dataMonth>=10 && dataDay<10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-"+(dataMonth)+"-0"+(dataDay+i)]; console.log("2019-"+(dataMonth)+"-0"+(dataDay+i))}
if(dataMonth>=10 && dataDay>=10){dateArray[i]=JSON.parse(historicalPrice).bpi["2019-"+(dataMonth)+"-"+(dataDay+i)]; console.log("2019-"+(dataMonth)+"-"+(dataDay+i))}
}
console.log("Data at "+i+" is: "+dateArray[i])
//console.log("2019-"+(month-1)+"-"+(day+i))
}
}
})
I am hoping to have the dates be stored in an array in the correct format, but instead everything gets very weird at the point when the month changes. It will skip a few days and then also start adding extra 0s to the front of numbers even when it shouldnt...
I am lost.
Thank you for you time.
As some have noted in the comments, there seems to be a bit of a readability issue, especially with all this date parsing / formatting. I would strongly consider looking into moment.js (or similar), where the primary date format you seem to desire is essentially iso8601 (so parsing too and from this format should be particularly painless!) :)
https://momentjs.com/docs/#/parsing/special-formats/
Nested ifs are generally undesired (if you can split the contents of an if into a separate function, then you should usually do so)
Your code is expecting everymonth has 31 days, you need to contrl that and im sure it will perform different at the moment it goes on for the next month :/
Situation: Some companies' weekends are Saturdays and Sundays or Fridays and Saturdays. So the calendar should be able to disable those day dynamically as following.
I have some basic idea of how to do it with javascript:
// determine weekends
if(dayType === 'fri' || dayType === 'sat') {
day.append($("<a class='disabled'>" + dayNum + "</a>").attr("data-day", dayNum).attr("data-month", monthNum).attr("data-year", yearNum));
}else {
day.append($("<a>" + dayNum + "</a>").attr("data-day", dayNum).attr("data-month", monthNum).attr("data-year", yearNum));
}
How to make it dynamic and based on companies' weekends after getting data from database using php?
if your javaScript does it, all you have to do is retrieve the information from the database and call a function that disable the days, the query to the database will depend on how it's designed, but you could create a table weekendDays and use the company name as search key (better an id), that way you could do a select days from weekenDays where name='Canonical'; days could be a string with comma separators... days = {"fri,sat"}, then you split the result and call disableDays sending the split text as parameter.
function disableDays(dayToDisable){
// determine weekends
for(idx=0; idx<dayToDisable.length; idx++){
if(dayType === dayToDisable[idx]) {
day.append($("<a class='disabled'>" + dayNum + "</a>").attr("data-day", dayNum).attr("data-month", monthNum).attr("data-year", yearNum));
}
else {
day.append($("<a>" + dayNum + "</a>").attr("data-day", dayNum).attr("data-month", monthNum).attr("data-year", yearNum));
}
}
}
You have to call the function with each result the query to the database returns (the weekends)
well something like that, please check the code I write it as an example and didn't test it, there could be better ways to do it :)
I figured something out: using CSS. Every 'div' for the days has got classes (wed past or sun future). So we have to just specify CSS for them. It's not related to OP but it's just for record.
I have a list of dates in an array(for now we can say that the dates are sorted). I want to have a script execute when the date matches a date in the array. My issue is figuring how to make this work on its own. I would like to have a server somehow act like an alarm clock that can run a script for a scheduled date and time. If anyone could help with suggestions to make this work I would appreciate it.
set date >>> if (currentDate == set date) >>> run script for the respective data
Please ask if you need clarification.
The way to do this with parse is a class with a date attribute. Create one object per date in your array of dates (they needn't be sorted).
Create a scheduled job that upon running, query's the class for the first date equal to the current date. If one is found, do whatever you want to do when an alarm is triggered.
So, something like...
Parse.Cloud.job("checkStatus", function(request, status) {
var today = new Date();
today.setHours(0, 0, 0, 0);
var tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
var query = new Parse.Query("MyAlarmClass");
query.greaterThanOrEqualTo('theDateAttribute', today);
query.lessThan('theDateAttribute', tomorrow);
return query.first().then(function(anAlarm) {
if (anAlarm) {
// do whatever should be done on the alarm
} else {
// do nothing
}
}).then(function() {
status.success();
}, function(error) {
status.error(JSON.stringify(error));
});
});
Schedule this to run at least twice per day (or faster than whatever resolution you need on the alarms).
I'm having problems with Meteor's subscribe. My goal is to search through my collection given criteria from user input form and spit back documents that match. My code works when I hard code let's say Meteor.subscribe('byProductAndBrand',1, 2) or whatever number instead of day and month. I tried the same numbers for day and month from the website, and it doesn't return any results. My variables seem to get the values from the html form because they print in the console, but for some reason they don't get passed in subscribe.Any suggestions?
The ScheduleList collection is just a bunch of documents with a certain hour, day, and month.
In the client:
Template.myform.events({
'click #submit' : function(event, template){
event.preventDefault();
Session.set('day', template.find('#day').value);
Session.set('month', template.find('#month').value);
var day = Session.get('day');
console.log(day);
var month = Session.get('month');
console.log(month);
var instance = Template.instance();
if(instance.byProductAndBrandHandle != null){
instance.byProductAndBrandHandle.stop();
}
instance.byProductAndBrandHandle = Meteor.subscribe('byProductAndBrand',day, month);
}
});
In the server:
Meteor.publish('byProductAndBrand', function(day, month){
var d = day;
var m = month;
return ScheduleList.find({day:d},{month: m});
});
The query limit in your server publication is incorrect, it should be:
ScheduleList.find({day:d, month: m});
Incidentally, one easy way to debug issues like this is to put a debugger; statement in your Meteor.publish function and then:
$ meteor debug
from the console. Then launch the Node Inspector in your browser at
http://localhost:8080/debug?port=5858
Then you can validate the parameter parsing and also double check your logic interactively. Sander's answer is correct though.