FullCalendar Display wrong StartDateTime/EndDatetime adding double GMT value - javascript

We are using FullCalendar.io library to our Salesforce LWC component. I am using timeZone = 'local'.
When returning the events from Server, browser inspector shows proper data, but when we open 'Fullcalendar'
it displays wrong time on client side. It doubles the GMT value.
E.g Event StartTime from server = 12:00 but when I convert it to GMT+1 it converts it to 14:00 instead of 13:00. Ideally it should only add 1 hour as per GMT+1, but it adds 2 hours.
For India Case where timezone = GMT+5:30, it adds 11 hours instead of 5:30. Please share your thoughts?
Here is the code:
#wire(fetchEvents)
eventObj(value){
this.eventOriginalData = value; //To use in refresh cache
///////
const {data, error} = value;
if(data){
//format as fullcalendar event object
let events = data.map(event => {
var sttime = new Date(event.StartDateTime);
var etime = new Date(event.EndDateTime);
var formattedStartTime = sttime.toString();
var formattedEndTime = etime.toString();
return { id : event.Id,
title : event.Subject,
start : formattedStartTime,
end : formattedEndTime};
});
this.events = JSON.parse(JSON.stringify(events));
console.log(this.events);
this.error = undefined;
//load only on first wire call -
// if events are not rendered, try to remove this 'if' condition and add directly
if(! this.eventsRendered){
//Add events to calendar
const ele = this.template.querySelector("div.fullcalendarjs");
$(ele).fullCalendar('renderEvents', this.events, true);
this.eventsRendered = true;
}
}else if(error){
this.events = [];
this.error = 'No events are found';
}
}
event.StartDateTime = 2022-12-07T12:00:00.000+0000 (Comming from Salesforce)
event.EndDateTime = 2022-12-07T13:00:00.000+0000 (Comming from Salesforce)
My TimeZone from where I open fullCalendar is GMT +1.
Tried with many different config. e.g toUTCString(). but still either it displays Server Original Date, or it converts and adds GMT double value.

Related

Google Apps Script: Reading Duration values is off by X minutes

I'm working with duration fields on Google Spreadsheet on my timezone
Here is an example of the data I'm working with and my Spreadsheet configuration
Sample data:
actividadID
destinoID
atractivoID
actividadDescripc
actividadDuracion
actividadTipo
da839da6
ae4f25ff
'46432440
Visita
1:00:00 a. m.
EspecĂ­fica
Script Objective
The idea is to loop through a subset of these fields so for that I'm grabbing all the values of the spreadsheet and filtering them:
function TourDuration(tourID, mySS) {
const touractivData = mySS.getSheetByName("TourActividad").getDataRange().getValues();
const activData = mySS.getSheetByName("Actividad").getDataRange().getValues();
var current_activList = touractivData.filter(function(item){
return item[1] == tourID; //Match Bot Numbers && Unprocessed trades
});
Logger.log("current_activList:");
Logger.log(current_activList);
When I check the result of the data I'm grabbing I see data that is off, going into negative not only by hours but also by minutes:
[da839da6, ae4f25ff, 46432440, Visita a la Plaza Mayor de Lima, Sat
Dec 30 01:08:36 GMT-05:00 1899, EspecĂ­fica]
(This one should be the equivalent to 1 hour, but instead I got a negative time)
My goal is to add all the durations that match my filter into a consolidated one without success.
Here is the full code at the moment:
function TourDuration(tourID, mySS) {
const touractivData = mySS.getSheetByName("TourActividad").getDataRange().getValues();
const activData = mySS.getSheetByName("Actividad").getDataRange().getValues();
var current_activList = touractivData.filter(function(item){
return item[1] == tourID; //Match Bot Numbers && Unprocessed trades
});
var current_activList_length = current_activList.length;
var total_duration = 0;
for(var i = 0; i < current_activList_length; i++){
var activDuration = activData.filter(function(item){
return item[0] == current_activList[i][2]; //Match Bot Numbers && Unprocessed trades
});
var duration = Utilities.formatDate(new Date(activDuration[0][4]), "GTM-5", "dd/MM/yyyy HH:mm");
var dur2 = new Date(activDuration[0][4]).toString().substr(25,6)+":00";
dateString = Utilities.formatDate(activDuration[0][4], dur2, "MM/dd/yyyy HH:mm:ss");
Logger.log(duration)
Logger.log(dur2)
Logger.log(dateString)
total_duration = total_duration;
}
}
And this is the result of the log for a register with a 45min duration:
Could it be that the App Script interface has a different timezone?
Although the minutes difference is hard to explain since usually the differences are in full hours.
Also, I don't plan on using getDisplayValue() since I need to consult the whole sheet and getDataRange() would be more efficient.
Explanation:
Also, I don't plan on using getDisplayValue() since I need to
consult the whole sheet and getDataRange() would be more efficient.
getDisplayValues is used instead of getValues() and its purpose is to get the displayed value as it is shown in the sheet.
Please refer to this post for more details:
Difference between getValue() and getDisplayValue() on google app script
On the other hand, getDataRange() is not a sophisticated function.
This expression:
const activSheet = mySS.getSheetByName("Actividad");
const activData = activSheet.getDataRange().getValues();
is identical to this:
const activSheet = mySS.getSheetByName("Actividad");
const activData = activSheet.getRange(1,1,activSheet.getLastRow(),
activSheet.getLastColumn()).getValues();
Towards the solution:
By using getDisplayValues you will be able to get the value as it is displayed in your sheet:
function TourDuration() {
const mySS = SpreadsheetApp.getActive();
const activSheet = mySS.getSheetByName("Actividad");
const activData = activSheet.getDataRange().getDisplayValues();
console.log(activData[1][4]); // 1:00:00
}
However, you can't take the full date from this expression because the date is not specified in the cell. If you expand the change the format of your cells in column E to date:
you will see that you are getting exactly the info that is stored in the cell. So the code works as expected. The issue has to do with the missing information in the sheet itself.
You need to store the correct date in your sheet:
and then if you change the format back to time, the date will still be correct and your current script will be able to get it properly.

Firestore/Javascript: How to get document data using timestamps?

I'm trying to create a line graph for my project. To accomplish this I need two date inputs from a user. From there my backend takes the inputs converts it to a javascript date object.
My problem is when I'm trying to convert the date objects to a firestore timestamp I get this error.
TypeError: t.getTime is not a function
at Function.ho.fromDate (timestamp.ts:27)
at Object.next (generateReportDateRange.php:158)
at subscribe.ts:104
at subscribe.ts:233
line (generateReportDateRange.php:158) pinpoints to this code:
var toTimeStampOne = firebase.firestore.Timestamp.fromDate(dateIdOne);
What that code does is to convert the date object to a firestore timestamp object. From there I am supposed to use toTimeStampOne as a query to get certain data from documents
here is the backend end code that may be related to the problem:
var dateIdOne = sessionStorage.getItem("dateOne");
var dateIdTwo = sessionStorage.getItem("dateTwo");
var dateSetArray = [];
var dataCal = [];
console.log(dateIdOne); //OUTPUT: Fri Mar 06 2020 08:00:00 GMT+0800 (Philippine Standard Time)
console.log(dateIdTwo); //OUTPUT: Tue Mar 10 2020 08:00:00 GMT+0800 (Philippine Standard Time)
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.userId = user.uid;
} //stores the user id in variable
var toTimeStampOne = firebase.firestore.Timestamp.fromDate(dateIdOne);
var toTimeStampTwo = firebase.firestore.Timestamp.fromDate(dateIdTwo);
var dateSetArray = [];
var dataCal = [];
let userRef1 = firebase.firestore().collection("users").doc(userId).collection("glucose")
.where("dateAdded", ">=", toTimeStampOne)
.where("dateAdded", "<=", toTimeStampTwo)
.limit(7);
return userRef1.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
this.dateSet = doc.data().bgReading;
dateSetArray.push(dateSet);
this.calDateAdded = doc.data().dateAdded.toDate();
const options = {
month: 'short',
day: 'numeric',
year: 'numeric'
};
const date = new Date(calDateAdded);
const americanDate = new Intl.DateTimeFormat('en-us', options).format(date);
dataCal.push(americanDate);
});
});
});
EDIT
here is the process of the conversion
//get date input from the forms and converts it to a js date object already
var data = {
dateOne: new Date($('#dateRangeOne').val()),
dateTwo: new Date($('#dateRangeTwo').val()),
};
//stores the date object to a session storage
sessionStorage.setItem("dateOne", data.dateOne);
sessionStorage.setItem("dateTwo", data.dateTwo);
You need to do
var dateIdOne = new Date(sessionStorage.getItem("dateOne"));
var dateIdTwo = new Date(sessionStorage.getItem("dateTwo"));
because
sessionStorage.setItem("dateOne", data.dateOne);
converts date to toString()
and
fromDate is a static method from the static Timestamp class from Firebase. If you want to store a field as a timestamp in Firestore, you'll have to send a JavaScript Date object or a Firestore Timestamp object as the value of the field
I'm going to go ahead and make the call that your "date" object is not actually a JavaScript Date object. It's probably just a formatted string. You won't be able to work with this very effectively if you're trying to query Firestore timestamp fields.
You're probably going to need to change whatever the source of data is that's feeding these lines of code:
var dateIdOne = sessionStorage.getItem("dateOne");
var dateIdTwo = sessionStorage.getItem("dateTwo");
You'll need to make sure that sessionStorage.getItem returns something suitable for querying Firestore. That could be a proper date object, or some unix time in milliseconds that you can easily convert into a Timestamp.
I like to create the full code structure but I already marked an answer. Regardless I will post the code here because it might help other people.
Get input value from forms and use sessionStorage to carry it over to another page
<script>
(function(){
$('#dateForm').on('submit', async function (e) {
e.preventDefault();
var data = {
dateOne: $('#dateRangeOne').val(),
dateTwo: $('#dateRangeTwo').val(),//get date input
};
if(data.dateOne.getTime() == data.dateTwo.getTime()){
alert("Please input a valid date range! Use the specific date generator to generate a daily report");
window.location.href = "generateReport.php";
}
else if(data.dateOne.getTime() > data.dateTwo.getTime()){
alert("Please input a valid date range!");
window.location.href = "generateReport.php";
}
else{
firebase.auth().onAuthStateChanged(function(user){
if(user){
this.userId = user.uid; //stores the userid
console.log(userId);
}
sessionStorage.setItem("dateOne", data.dateOne);
sessionStorage.setItem("dateTwo", data.dateTwo);
setTimeout(function(){
window.location.href = "generateReportDateRange.php";
}, 3000);
});
}
});
})
();
</script>
The query code (Getting document data based on two Firestore timestamp objects)
<script>
var dateIdOne = new Date(sessionStorage.getItem("dateOne"));
var dateIdTwo = new Date(sessionStorage.getItem("dateTwo"));
firebase.auth().onAuthStateChanged(user => {
if(user){
this.userId = user.uid;
} //stores the user id in variable
var toTimeStampOne = firebase.firestore.Timestamp.fromDate(dateIdOne);
var toTimeStampTwo = firebase.firestore.Timestamp.fromDate(dateIdTwo);
let userRef1 = firebase.firestore().collection("users").doc(userId).collection("glucose")
.where("dateAdded", ">=", toTimeStampOne)
.where("dateAdded", "<=", toTimeStampTwo)
.limit(7);
//PERFORM GET DOC DATA HERE
});
</script>

How to compare dates to make sure Google Apps Script is only sending an alert once a day?

I have a script in a Google Sheet that is sending out an alert if a certain condition is met. I want to trigger the script to run hourly, however, if an alert was already sent out today, I don't want to send out another one (only the next day). What is the best way to achieve this?
I've tried formatting the date several ways, but somehow the only thing working for me so far is getting the year, month and day from the date object as int and comparing them separately.
function sendAlert{
var now = new Date();
var yearNow = now.getYear();
var monthNow = now.getMonth() + 1;
var dayNow = now.getDate();
var sheet = SpreadsheetApp.getActive().getSheetByName('CHANGE_ALERT');
var sentYear = sheet.getRange("R2").getValue();
var sentMonth = sheet.getRange("S2").getValue();
var sentDay = sheet.getRange("T2").getValue();
if (yearNow != sentYear || monthNow != sentMonth || dayNow != sentDay) {
sendEmail();
var sentYear = sheet.getRange("R2").setValue(yearNow);
var sentMonth = sheet.getRange("S2").setValue(monthNow);
var sentDay = sheet.getRange("T2").setValue(dayNow);
else {
Logger.log('Alert was already sent today.');
}
}
I think this solution is definitely not the best approach, but I cannot come up with another that merges the date into one. Only comparing the new Date() doesn't work, since the time of day will not necessarily be the same. If I format the date to YYYY-MM-dd, it should work, but then when I get the date again from the spreadsheet it gets it as a full date with the time again.
Requirement:
Compare dates and send an email if one hasn't been sent already today.
Modified Code:
function sendAlert() {
var sheet = SpreadsheetApp.getActive().getSheetByName('blank');
var cell = sheet.getRange(2,18); //cell R2
var date = new Date();
var alertDate = Utilities.formatDate(cell.getValue(), "GMT+0", "yyyy-MM-dd");
var currentDate = Utilities.formatDate(date, "GMT+0", "yyyy-MM-dd");
if (alertDate !== currentDate) {
sendEmail();
cell.setValue(date);
} else {
Logger.log('Alert was already sent today.');
}
}
As you can see, I've removed all of your year/month/day code and replaced it with Utilities.formatDate(), this allows you to compare the dates in the format you specified in your question. I've also changed the if statement to match this, so now we only need to compare alertDate and currentDate.
References:
Utilities.formatDate()
Class SimpleDateFormat

Google Form on Submit get values and format the time

I am using Google Apps Script with a Google form. When the user submits the Google Form I get a value from a question. I then take that value and make it a date object, from what I saw on this post about daylight savings I use that to determine the timezone. I run the date object through Utilities.formatDate and want to get the correctly formatted date.
example: 9:00 AM
But instead I am getting a completely different time than expected.
My question is: Can someone help me understand why the below code is outputting a time that is 3 hours different?
function onSubmit(e) {
var values = e.values;
Logger.log(values);
try {
var start1 = new Date(values[3]);
var startN = new Date(start1).toString().substr(25,6)+"00";
var startT = Utilities.formatDate(start1, startN, "h:mm a");
Logger.log(startT);
} catch(error) {
Logger.log(error);
}
}
The assumption that Utilities formatDate does not support GMT... parameter is not true.
The post you mentioned in reference is used to get calendar events and is a useful way to get the right value when you get events from another daylight saving period (getting the TZ info from the calendar event itself), for example events for next month will be in "summer time" while we are still in "winter time"...
Your issue might come from different sources depending on time zone settings of your script vs timezone of the source. Could you describe the exact configuration in which you use this script ?
In the mean time, here is a small code that demonstrates how the code is working + the logger results :
function testOnSubmit() {
var eventInfo = {};
var values = {};
values['3'] = new Date();
eventInfo['values'] = values;
Logger.log('eventInfo = '+JSON.stringify(eventInfo)+'\n\n');
onSubmit(eventInfo);
}
function onSubmit(e) {
var values = e.values;
try {
var start1 = new Date(values[3]);
Logger.log('onSubmit log results : \n');
Logger.log('start1 = '+start1)
var startN = new Date(start1).toString().substr(25,6)+"00";
Logger.log('startN = '+startN);
var startT = Utilities.formatDate(start1, startN, "h:mm a");
Logger.log('result in timeZone = '+startT);
} catch(error) {
Logger.log(error);
}
}
EDIT : additionally, about the 30 and 45' offset, this can easily be solved by changing the substring length like this :
var startN = new Date(start1).toString().substr(25,8);
the result is the same, I had to use the other version a couple of years ago because Google changed the Utilities.formatDate method at some moment (issue 2204) but this has been fixed.
EDIT 2 : on the same subject, both methods actually return the same result, the GMT string has only the advantage that you don't have to know the exact timezone name... there is also the Session.getScriptTimeZone() method. Below is a demo script that shows the resulst for 2 dates in January and July along with the log results :
function testOnSubmit() {
var eventInfo = {};
var values = {};
values['3'] = new Date(2014,0,1,8,0,0,0);
eventInfo['values'] = values;
Logger.log('eventInfo = '+JSON.stringify(eventInfo)+'\n\n');
onSubmit(eventInfo);
values['3'] = new Date(2014,6,1,8,0,0,0);
eventInfo['values'] = values;
Logger.log('eventInfo = '+JSON.stringify(eventInfo)+'\n');
onSubmit(eventInfo);
}
function onSubmit(e) {
var values = e.values;
var start1 = new Date(values[3]);
Logger.log('onSubmit log results : ');
Logger.log('start1 = '+start1)
var startN = new Date(start1).toString().substr(25,8);
Logger.log('startN = '+startN);
Logger.log('result in timeZone using GMT string = '+Utilities.formatDate(start1, startN, "MMM,d h:mm a"));
Logger.log('result in timeZone using Joda.org string = '+Utilities.formatDate(start1, 'Europe/Brussels', "MMM,d h:mm a"));
Logger.log('result in timeZone using Session.getScriptTimeZone() = '+Utilities.formatDate(start1, Session.getScriptTimeZone(), "MMM,d h:mm a")+'\n');
}
Note also that the Logger has its own way to show the date object value ! it uses ISO 8601 time format which is UTC value.
Try this instead:
var timeZone = Session.getScriptTimeZone();
var startT = Utilities.formatDate(start1, timeZone, "h:mm a");
The Utilities.formatDate function expects a time zone that is a valid IANA time zone (such as America/Los_Angeles), not a GMT offset like GMT+0700.
I am making the assumption that Session.getScriptTimeZone() returns the appropriate zone. If not, then you might need to hard-code a specific zone, or use a different function to determine it.
Additionally, the +"00" in the script you had was assuming that all time zones use whole-hour offsets. In reality, there are several that have 30-minute or 45-minute offsets.

google apps script - createEvent error indicating NaN

Can anyone assist in why I'm getting a "NaN" for dates in the code below? I'm trying to create a calendar event but it keeps giving indicating "NaN" in the Logger.log. Execution transcript shows the following;
"Execution failed: Cannot find method createEvent(string,number,number). (line 38, file "Code")"
This is part of the code. The script runs based on a form submit of two dates. The script grabs the values from a spreadsheet. For example the two dates could be 4/1/2014 and 4/2/2014.
Here is the code:
var ptoCalendar = CalendarApp.getCalendarById("ENTER CALENDAR ID")
var startDate = Utilities.formatDate(new Date(sheet.getRange(i,j-3,1,1).getValue()), 'GMT', "yyyy-MM-dd'T'HH:mm:ss");
var cnvtStartDate = new Date(startDate).setHours(08,00,00);
Logger.log(cnvtStartDate);
var endDate = Utilities.formatDate(new Date(sheet.getRange(i,j-2,1,1).getValue()), 'GMT', "yyyy-MM-dd'T'HH:mm:ss");
var cnvtEndDate = new Date(endDate).setHours(17,00,00);
Logger.log(cnvtEndDate);
var createEvent = ptoCalendar.createEvent(recipientName+'- PTO', cnvtStartDate, cnvtEndDate);
Any assistance is appreciated..
UPDATED CODE PRIOR TO Serge Response - My solution at the moment. NOTE: I'm providing the full function here, were as before was just a snippet
//This takes the date string from managersDecission() and covnerts back to a date type
function parseDate(dateString){
var time = Date.parse(dateString);
if(!time){
time = Date.parse(dateString.replace("'T'"," "));
if(!time){
bound = dateString.indexOf('T');
var dateData = dateString.slice(0, bound).split('-');
var timeData = dateString.slice(bound+1, -1).split(':');
time = Date.UTC(dateData[0],dateData[1]-1,dateData[2],timeData[0],timeData[1],timeData[2]);
}
}
return new Date(time);
}
//Used to update the employee requested PTO in the request spreadsheet with managers decision
function managersDecission() {
//Section get the tracking spreadsheet and its values & requests the decision made by manager in grabRequestID()
var ss = SpreadsheetApp.openById(trackingSS)
var sheet = ss.getSheetByName('Requests');
var data = sheet.getDataRange().getValues();
var decision = grabRequestID();
//for loop to set the decision of the manager for tracking
for (var i=0; i < data.length; i++) {
for (var j=0; j < data[i].length; j++) {
if (data[i][j] == decision[0] && decision[1] == "Approved") {
sheet.getRange(i+1,j+3,1,1).setValue(decision[1]);
var recipientEmail = sheet.getRange(i+1,j,1,1).getValue();
var recipientName = sheet.getRange(i+1,j-1,1,1).getValue();
//This section creates the calendar event for approved PTO
var ptoCalendar = CalendarApp.getCalendarById('CALENDAR ID')
var startDate = Utilities.formatDate(new Date(sheet.getRange(i+1,j-3,1,1).getValue()), 'GMT', "yyyy-MM-dd'T'HH:MM:SS");
//Debug Line
//Logger.log("start date is "+startDate)
var cnvtStartDate = parseDate(startDate);
//Debug Line
//Logger.log("parsed start date "+cnvtStartDate);
var setHourStartDate = cnvtStartDate.setHours(08,00,00,00);
//Debug Line
//Logger.log("start Hours set "+setHourStartDate);
var endDate = Utilities.formatDate(new Date(sheet.getRange(i+1,j-2,1,1).getValue()), 'GMT', "yyyy-MM-dd'T'HH:MM:SS");
//Debug Line
//Logger.log("end date is "+endDate);
var cnvtEndDate = parseDate(endDate);
//Debug Line
//Logger.log("parse end date "+cnvtEndDate);
var setHourEndDate = cnvtEndDate.setHours(15,00,00,00);
//Debug Line
//Logger.log("end Hours set "+setHourEndDate);
var createEvent = ptoCalendar.createEvent(recipientName+'- PTO', cnvtStartDate, cnvtEndDate);
ADDING LOG INFO FOR SERGE'S BELOW COMMENT
[14-03-20 16:08:05:541 PDT] start date is 2014-03-31T07:03:00
[14-03-20 16:08:05:545 PDT] parsed start date Mon Mar 31 2014 00:03:00 GMT-0700 (PDT)
[14-03-20 16:08:05:545 PDT] start Hours set 1396278000000
[14-03-20 16:08:05:546 PDT] end date is 2014-04-02T07:04:00
[14-03-20 16:08:05:547 PDT] parse end date Wed Apr 02 2014 00:04:00 GMT-0700 (PDT)
[14-03-20 16:08:05:547 PDT] end Hours set 1396476000000
UPDATED DID SOME TESTING BASED ON Serge comment indicating cnvtStartDate was a date object
I removed the Utilities.formatDate and in fact the value pulled from spreadsheet is a date value and will allow script to run successfully. Issue was that is creates the calendar event for 12:00AM. Since this should block a full work day out (PTO day), I need it to set some times for start /end.
When running the script now and using the following:
var startDate =new Date(sheet.getRange(i+1,j-3,1,1).getValue());
var setHourStartDate = startDate.setHours(08,00,00,00);
var endDate = new Date(sheet.getRange(i+1,j-2,1,1).getValue());
var setHourEndDate = cnvtEndDate.setHours(15,00,00,00);
var createEvent = ptoCalendar.createEvent(recipientName+'- PTO', setHourStartDate, setHourEndDate);
The following error is giving. It thinks the ssetHourStartDate and end is a number??
"Execution failed: Cannot find method createEvent(string,number,number)."
I then adjusted he code to the following:
var startDate =new Date(sheet.getRange(i+1,j-3,1,1).getValue());
var setHourStartDate = new Date(startDate.setHours(08,00,00,00));
var endDate = new Date(sheet.getRange(i+1,j-2,1,1).getValue());
var setHourEndDate = new Date(endDate.setHours(17,00,00,00));
var createEvent = ptoCalendar.createEvent(recipientName+'- PTO', setHourStartDate, setHourEndDate);
And all is working well. It will create single day event for the full day or span multiple days across the top of calendar.
Thanks Serge as always for pointing thing out ..
why do you use Utilities.formatDate in the first place ?
If the cell in the sheet is a date you don't need to convert it to a string, just use it as it is.
If you really want to use it that way then use the correct syntax like below :
var cnvtStartDate = new Date("2014/03/20"):// I replaced with the string "as it should be"
cnvtStartDate.setHours(8,0,0,0);
Logger.log(cnvtStartDate);// this is a date object

Categories

Resources