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

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>

Related

FullCalendar Display wrong StartDateTime/EndDatetime adding double GMT value

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.

How can i convert date to timestamp or preferably how can i add n number of days to a timestamp in javascript

I am working on firebase cloud functions that i'm new to , using javascript. I have a need to add n number of days to a user who has renewed a subscription.
Here is part of the function
...
var sellerRef = admin.firestore().doc('sellerProfile/'+req.query.sellerId)
var seller = sellerRef.get().then(snapshot=>{
const data= snapshot.data()
var currentDate = data.subscriptionDeadline.toDate()
Date.prototype.addDays= function(d){
this.setDate(this.getDate() + d);
return this;
};
var newDate = currentDate.addDays(30);
res.send(newDate)
})
sellerRef.update({
subscriptionDeadline: Date.parse(newDate)
})
...
In that code i got the subscription deadline of an individual then used a prototype to add 30 days as a subscription renewal. How do i convert the days back to timestamp to be able to save the new subscription deadline to firestore or better if i could add the 30 days without converting the timestamp to date.
Firestore Timestamps objects don't offer any date math operations. It will be easier if you do convert the Timestamp into a Date (or something else that lets you do math), the convert back to a Timestamp.
const timestamp = data.subscriptionDeadline;
const date = timestamp.toDate();
const laterDate = new Date(date.getTime() + 30*60*60*1000);
const laterTimestamp = admin.firestore.Timestamp.fromDate(laterDate);

Insert wrong date in MongoDB

I am tring to save dates in my MongoDB table using C#.
Here is a JavaScript logic that send data using Ajax to C# controller
$(function ($, w, d) {
var _user = {}
//var time = moment("2016-04-02", "YYYYMMDD").fromNow()
//var bime = moment().endOf('day').fromNow();
//var crime = moment("20120620", "YYYYMMDD").fromNow();
// document.getElementById('time').innerHTML = time;
var obj = {};
var holidaylist = ["Mar-31-2018", "Apr-01-2018","Apr-04-2018","Apr-07-2018","Apr-08-2018"];
var startdate = new Date("Apr-02-2018");
obj.endDate = "Apr-06-2018";
obj.holidaylist = holidaylist;
obj.NumberOfCount = 9;
CallAjax("POST", '/LeaveManagement/', 'checkleavelogic', obj, onsuccessaddemployee, '');
here is the C# logic that saves the data in MongoDB:
public JsonResult checkLeaveLogic(LeaveLogicModel leaveLogic)
{
string strconnectiomstring = "mongodb://10.10.32.125:27017";
MongoClient Client = new MongoClient(strconnectiomstring);
var DB = Client.GetDatabase("TimeClock");
List<DateTime> leavesDate = new List<DateTime>();
var collection = DB.GetCollection<LeaveLogicModel>("leaves1");
collection.InsertOne(leaveLogic);
}
Now this is the MongoDB table that saves as a previous date.
Here you can see that my StartDate is Apr-02-2018 but it saves as Apr-01-2018 and for all date it is the same.
Can someone tell me where I am wrong?
When you create new dates with just date or date and time, it usually creates them in the same timezone as the program is.
So if you dont specify the timezone, it becomes the timezone the server is in. When you save to Mongo, the Date is serialized to UTC -> zero timezone.
Create the dates with +00:00 timezone and you should have consistent data.
It's a good practice to set your datetimes to UTC, however if you want to convert it, you can use something like this.
var date = DateTime.UtcNow;
TimeZoneInfo.ConvertTime(date, TimeZoneInfo.Local);

Conflicting dates in mongoose and express.js

The problem occurs when I declare my schema with type Date rather than String.
Case I:
var MySchema = new Schema({
created_at: {type: String, default: ''}
});
With this shema declaration I use moment.js moment-timezone module for declaring current time in Asia/Kolkata timezone.
var tmoment = require('moment-timezone');
var currentTime = tmoment().tz('Asia/Kolkata').format('llll');
And I am able to get the correct time.
Case II:
var MySchema = new Schema({
created_at: {type: Date, default: ''}
});
With this shema declaration I use moment.js moment-timezone module for declaring current time in Asia/Kolkata timezone.
var tmoment = require('moment-timezone');
var currentTime = tmoment().tz('Asia/Kolkata').format('llll');
But now the time is not coming according to the timezone. I even tried with the following declaration
var tmoment = require('moment-timezone');
var currentTime = tmoment().tz('Asia/Kolkata').format();
But could not find a solution.
When you are saving dates to a mongo database, you can simply save a javascript Date object regardless of timezone. (Using the Date type as in case 2.) Then you would use moment to display the date in whatever timezone you require.
To save the object:
var id = ...
var saveReq = new RequestModel({ _id: id, created_at: new Date() });
saveReq.save(function (err, result) {
// ...
});
To read the object from the database, and then display the localized date string:
var tmoment = require('moment-timezone');
RequestModel.findOne({_id: id}, function (err, doc) {
if(err) {} // ...
var created = doc.created_at;
var display = tmoment(created).tz('Asia/Kolkata').format('llll');
console.log(display);
});
change server timezone to your local timezone.

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.

Categories

Resources