Google Scripts - "If" comparison not working - javascript

I want to protect the document from other users if a date in Column B1 + 2days is greater than today.
I had no problem with protection part, but I can't get the IF statements to work for some weird reason I can't understand.
This is the script where i compare dates:
ss = SpreadsheetApp.getActiveSheet();
send_date = ss.getRange("B1").getValue();
limit = new Date(send_date.setDate(send_date.getDate()-2))
limit.setHours(0,0,0,0)
day0 = new Date();
day0.setHours(0,0,0,0)
ss.getRange("D1").setValue(day0);
ss.getRange("D2").setValue(limit);
ss.getRange("D3").setValue(limit>day0);
ss.getRange("D4").setValue(limit<=day0);
if (day0>limit) { ss.getRange("C1").setValue("can be edited");}
else if (day0<=limit) { ss.getRange("C1").setValue("cannot be edited");}
I set hours/minutes/seconds etc to 0 because I only need to compare the dates day by day.
What happens after I run the script?
For example, if B1 = '2017-10-24', D1 sets to today ('2017-10-26'), D2 sets to ('2017-10-22').
D3, with limit>day0 comparison gets value FALSE, D4 limit<=day0 gets TRUE.
So far so good, but when it comes to IF statements, it seems that these comparisons are reversed.
In this example, C1 is set to 'can be edited'.
For me, that means that first comparison return FALSE, the second returned TRUE.
When I set date to a date in future (i.e. '2017-10-30'), D1-D4 fields get the right values, but C1 is set to 'cannot be edited'.
I'll be grateful for any help.

You can not compare two objects (day0 and limit) like that.
But, you can compare a value of those two objects. For example, using getTime().
var day0Time = day0.getTime();
var limitTime = limit.getTime();
if (day0Time > limitTime) {
// do stuff
}

Related

I am having trouble with the logic flow of this code, and the resulting incorrect output

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 :/

Spreadsheet function does not run when button clicked

I previously asked a two-part question, and only one part was answered and then closed, while the other part was left unanswered. I'm re-asking that part.
I'm in charge of creating an "automatic" project tracking sheet for my team. Automatic in the sense that someone presses a button, it logs a date/time stamp, and the time they spent on said project is automatically calculated for them.
However, when I connect a script to a Google Drawing to act as a button, it doesn't do anything, and I am unable to figure out why.
Here is what my spreadsheet looks like, with a button (drawing) configured to run the timeStamp() function when clicked:
You can also get a copy of the spreadsheet here.
The code I've got so far:
function timeStamp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var timezone = ss.getSpreadsheetTimeZone;
var timeFormat = "hh:mm a";
var lastCol = sheet.getLastColumn();
var lastRow = sheet.getLastRow();
var lastCell = sheet.getRange(lastRow, lastCol);
var timeStampCell = sheet.getRange(lastRow, lastCol + 1);
if(timeStampCell === " ") {
var date = Utilities.formatDate(new Date(), timezone, timeFormat);
timeStampCell.setValue(date);
};
}
var timeStampCell = sheet.getRange(lastRow, lastCol + 1);
...sets timeStampCell to a Range object.
if(timeStampCell === " ") {
...compares that Range object to a String containing a single space character. The comparison is always false, because the types are different. If == was used for the comparison with type coercion allowed, it would still evaluate false because the operands are just different.
You probably want the cell's contents, and to compare them to an empty string:
if(timeStampCell.getValue() === "")
Note: take care using === with the contents of Spreadsheet cells. If the comparison is for Date objects, === will evaluate true only when both operands are the exact same object. See Which equals operator (== vs ===) should be used in JavaScript comparisons?
In this example, you don't really care what data type comes from the spreadsheet, only that it is blank. Therefore, you could use ==.
if(timeStampCell.getValue() == "")
Another problem, here:
var timezone = ss.getSpreadsheetTimeZone;
This will get a reference to the Spreadsheet "getSpreadsheetTimeZone" method, but it will not tell you the timezone. To get the result of the method, you need to call it by including parentheses:
var timezone = ss.getSpreadsheetTimeZone();
With those two changes, the script works for me.

SharePoint/Javascript: comparing calendar date times in javascript

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.

JavaScript calculate difference between two dates, display number in text input

I have been working for some time on an application form for an insurance company. They sell travel insurance.
As an additional small feature they have asked me to take the dates the depart and return dates the user inputs, calculate the number of days between them and then display number in the 'days' box. The goal of which is so that the user can enter the two dates and have the number of days auto-calculated.
I have already created a function which properly calculates the date and I have tested it using manually assigned date values.
My issue has come up when using the JS calendar.
What I tried to do was use the onblur of the second box to access the function and spit the date out into the 'days' box. I quickly realized that the onblur is triggered before the code for the JS calendar puts in the date, hence there is no date for the function and the function does not run.
I then tried to use onchange and realized it would not work either because the user is not actually changing the date, code is.
So what I tried to do next was use an Interval to trigger the function, this is where I have run into issues.
Below is my code in my caldate.js file which is attached to my HTML form.
var namestart = new Array ();
namestart[0] = "trav_emer_single_date_go";
namestart[1] = "trav_emer_extend_date_go";
namestart[2] = "allinc_single_date_go";
namestart[3] = "allinc_annual_date_go";
namestart[4] = "cancel_date_go";
namestart[5] = "visitor_supervisa_date_go";
namestart[6] = "visitor_student_date_go";
namestart[7] = "visitor_xpat_date_go";
var namend = new Array ();
namend[0] = "trav_emer_single_date_ba";
namend[1] = "trav_emer_extend_date_ba";
namend[2] = "allinc_single_date_ba";
namend[3] = "allinc_annual_date_ba";
namend[4] = "cancel_date_ba";
namend[5] = "visitor_supervisa_date_ba";
namend[6] = "visitor_student_date_ba";
namend[7] = "visitor_xpat_date_ba";
var names = new Array ();
names[0] = "trav_emer_single_days";
names[1] = "trav_emer_extend_days";
names[2] = "allinc_single_days";
names[3] = "allinc_annual_days";
names[4] = "cancel_days";
names[5] = "visitor_supervisa_days";
names[6] = "visitor_student_days";
names[7] = "visitor_xpat_days";
function daysBetween() {
for (var i = 0; i < 8; i++) {
//Get the value of the current form elements
var start = document.getElementById(namestart[i]).value;
var end = document.getElementById(namend[i]).value;
//Duration of a day
var d = 1000*60*60*24;
// Split Date one
var x = start.split("-");
// Split Date two
var y = end.split("-");
/// // Set Date one object
var d1 = new Date(x[0],(x[1]-1),x[2]);
// // Set Date two object
var d2 = new Date(y[0],(y[1]-1),y[2]);
//
// //Calculate difference
diff = Math.ceil((d2.getTime()-d1.getTime())/(d));
//Show difference
document.getElementById(names[i]).value = diff;
}
}
function interval() {
var int = setInterval(function(){daysBetween()},500);
}
The list of arrays at the beginning is the names of the elements which I need to access. What I intend to do with my function is on each interval run through a loop which checks all 8 of these elements. namestart[] and namend[] are the start and end dates entered by the user. names[] lists the names of the boxes where days are to be displayed.
I have not been able to even test the interval portion because I can't even get the daysBetween() to run once with manually assigned value="date" for testing purposes, it just won't run at all.
The issue is quite simple really: document.getElementById(namestart[i]).value isn't pullig out a value, it just hangs the script because it can't find the value. I have also tried using the form_name.elements().value notation and the form_name.element_name.value notation to no avail.
I am really stumped here as far as I can tell the code should be working, I give a list of the names of the items and I tell the script to access them using - what I have used, and seen many times to work getElementByID.
Any assistance would be greatly appreciated as I am not quite sure where to go from here.
As requested here is a JS fiddle link: http://jsfiddle.net/L2H9N/ - pure JS no libraries.
What I think is happening is your daysBetween function is executing before the DOM is ready, which is throwing an error and nuking the rest of your javascript. To fix it, you'll need to put the call to daysBetween into a callback for window.onload or attach it to a callback in your calender.
It would also be a good idea to coalesce your nulls or at least check for them before proceeding to do calculations on the variables.

JavaScript - Compare two timestamps

i try to compare two timestamps like this:
var nowDate = new Date();
var givenDate = new Date(parseInt(year), parseInt(month), parseInt(day), parseInt(hour), parseInt(minute), 0);
var nd_timestamp = nowDate.getTime();
var gd_timestamp = givenDate.getTime();
if (nd_timestamp > gd_timestamp) {
alert("yes");
}
But it is not working properly. If i look at the nd_timestamp and gd_timestamp everything looks fine, but the if-clause is not working. If i remove the parseInt(year)... and enter Date(2012, 04, 20, 0, 0, 0) the if-clause is working.
The variables year, month etc. comes through a function, but if i debug it with alert(year) etc. everything is fine. The given date through the form is smaller than the actual date.
Does anybody know why it is not working with variables?
Thanks!
You should check the values you pass to the Date constructor for validity, which includes explicitly specifying 10 as the second parameter to all of your parseInt calls to avoid nasty surprises.
Regarding the second parameter, the documentation says
While this parameter is optional, always specify it to eliminate
reader confusion and to guarantee predictable behavior. Different
implementations produce different results when a radix is not
specified.
You have to take 1 from Month because for some reason it is zero based, unlike the others.

Categories

Resources