Retrieving a date from Firestore in Node.js - node.js

From the Firestore documentation on saving data of supported types, I red:
var docData = {
//...
dateExample: new Date("December 10, 1815"),
//...
}
};
db.collection("data").doc("one").set(docData).then(function() {
console.log("Document successfully written!");
});
This is what I use in my Cloud Functions to save various dates to Firestore.
It works great !
My problem comes when I need to retrieve those dates and post them as String to a third party API.
As far as I understood, in Firebase/Firestore, dates are stored as a Unix Timestamp.
I couldn't find anywhere (firebase doc, stackoverflow ...) how to convert it properly to a String.
I tried unsuccessfully the following:
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp * 1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
var hour = a.getHours();
var min = a.getMinutes();
var sec = a.getSeconds();
var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
return time;
}
admin.firestore().collection('users').doc(userId).get()
.then( (doc) => {
const user = doc.data();
const birthDate = user.birthDate;
const birthDateString = timeConverter(birthDate);
console.log(`birthDateString =${birthDateString}`);
// "birthDateString = NaN undefined NaN NaN:NaN:NaN"
});

First you can use toDate() to convert the Firebase timestamp to a Date object and then use the Date's object method toDateString() to convert it to a String.
const birthDate = user.birthDate.toDate();
const birthDateString = birthDate.toDateString();
You can also check out Moment.js, it helps a lot when dealing with Dates and displaying them.

This boils down to : how do I convert a unix timestamp to a human readable date?
There are several ways to do this but one of the easiest is to use
var readableData = new Date(doc.data().myUnixTimestamp).toLocaleDateString("en-US");
There are options for all locales. See MDN's Date.prototype.toLocaleDateString.

Related

Moment is getting the wrong date in Node JS mssql query

I am trying to pass moment dates as variables in a query. When I console log the dates are correct but when the query runs it gets the current date -1...
Here is the code:
const dateEnd = moment().format('YYYY-MM-DD 23:59:59');
const dateStart = moment().format('YYYY-MM-DD 00:00:00');
// console.log(dateEnd)<-- They come back correct
// console.log(dateStart)
// process.exit();
let pool = await sql.connect(dbconfig)
//Get records from table
let getRecords = await pool.request()
.input('dateStart', sql.Date, dateStart)
.input('incrm', sql.VarChar, 'yes')
.input('dateEnd', sql.Date, dateEnd)
.query('select * from database.dbo.table where someValue in (231312,7132133) and incrm=#incrm and processeddate between #dateStart and #dateEnd and email is not null')
The node-mssql library expects dates to be passed as Date objects.
Try this, if you want the current day in the same time zone as the machine you're running this code from:
const dateStart = moment().startOf('day').toDate();
const dateEnd = moment().endOf('day').toDate();
Or, if you want the current UTC day, then:
const dateStart = moment.utc().startOf('day').toDate();
const dateEnd = moment.utc().endOf('day').toDate();
Or, if you want the current day in a particular time zone (say US Central Time), then use the moment-timezone add-on library:
const dateStart = moment.tz('America/Chicago').startOf('day').toDate();
const dateEnd = moment.tz('America/Chicago').endOf('day').toDate();
All three of these assume that the processeddate is in terms of UTC in your database.
You should probably also pass sql.DateTime2 instead of sql.Date.

Compare two Firestore Timestamps in Cloud Functions

I'm writing update function in Firestore and I want to compare two Timestamp. I've tried multiple things but not working. Can you point me correct way of comparing two Timestamp in firestore.
exports.updateFunction = functions.firestore
.document('xyz/{xyzId}')
.onUpdate((change, context) => {
var updatedXYZ = change.after.data();
var oldXYZ = change.before.data();
var newTimestamp = updatedXYZ.timing;
var oldTimestamp = oldXYZ.timing;
// I've tried following things but not working
var result = newTimestamp === oldTimestamp; // not working
var result = new Date(newTimestamp) - new Date(oldTimestamp); // not working
return true;
});
I want to check two Timestamp is same or not.
Consult the API docs for Firestore's Timestamp object. Timestamp has a method called isEqual() that will compare two timestamps.
var result = newTimestamp.isEqual(oldTimestamp);
You need to add this line
admin.firestore().settings( { timestampsInSnapshots: true })
in your index.js file.
After adding this line cloud function will read your timestamp field as Timestamp Datatype. Now you can compare two timestamps using
var result = newTimestamp.isEqual(oldTimestamp);
//I assume you have yourTimestampInMilliseconds
const currentTimestamp = Date.now();
console.log("(currentTimestamp <= yourTimestampInMilliseconds)= "+ (currentTimestamp <= yourTimestampInMilliseconds));
console.log("(currentTimestamp > yourTimestampInMilliseconds)= "+ (currentTimestamp > yourTimestampInMilliseconds));

Checking the time difference 24 hours from now using Moment

My goal is to build a feature like snapchat, 24 hours from now the content that I post will be deleted. I want to create an API that will check whether the current time has past 24 hours or not, if past then It will delete it, it will check the created time and the current time, and it will compare between these two time.
I use moment to store dates/time to database. Let say that my database code looks like this
var mongoose = require('mongoose');
var moment = require('moment');
var ItemPost = new Schema({
name: String,
created: { type: Date, default: moment() },
timeLeft: { type: Number, default: 24 },
});
For example if I post a content right now
11:31 PM 8 Jan 2017
Assume that the time right now is of the above. Let say 9 hours has passed, and the current time is
08:31 PM 9 Jan 2017
How would I get the difference in time 24 hours from the created date?
My attempt
function checkTime(item) {
var currentTime = moment();
// assume item is an ItemPost object from the database
var timeStore = item.created()
// Im stuck here, I tried various codes. But nothing has worked so Far.
return data;
}
The result that I want is
console.log(checkTime(item)); // 1 or 1 hour
My real attempt of getting close to my goal is
function test0() {
var currentTime = moment();
var timeStored = moment().subtract(7, 'hours');
var hoursMinus = timeStored.fromNow(currentTime);
console.log(hoursMinus); // 7 hours - it is a string
timeDiff = hoursMinus.substr(0, hoursMinus.indexOf(' ')); // will get just 7
var timeLeft = 24; // Default data from database
console.log(timeLeft - parseInt(timeDiff));
}
Well this solution work well, if I subtract 7
var timeStored = moment().subtract(7, 'hours');
But it won't work if the time is more or equal than 23
var timeStored = moment().subtract(23, 'hours');
var hoursMinus = timeStored.fromNow(currentTime);
console.log(hoursMinus); // Will return "a day"
hoursMinus will return a day as the value which is bad for my algorithm
My goal is to return a data that says 1 hour left or 7 hours left from the original created date. Any help would be appreciated.
You can use moment diff method.
Here a working example:
function checkTime(item) {
var currentTime = moment();
var timeStore = moment(item.created);
return currentTime.diff(timeStore, 'h');
}
// Example Date object representing 5 hours ago
var item = {created: moment().subtract(5, 'h').toDate()};
var res = checkTime(item);
console.log(res); // 5
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>

new Date() Scheduled Script returning UTC not local time

I have a function in my library to return the current date:
function currentDate(addDays) {
if (addDays == null||addDays == undefined) {
addDays = 0;
}
var currentdate = new Date();
var current = nlapiAddDays(currentdate,addDays);
var day = current.getDate();
var month = current.getMonth()+1
var year = current.getFullYear();
return day+'/'+month+'/'+year;
}
All works fine, until I run a scheduled script which utilises this function, at which point the date returned is UTC, not our local time. Is there a simplistic method of conversion within this function without the need for external libraries?
Here is a utils function that I've used for years.
function getCompanyDate(){
var currentDateTime = new Date();
var companyTimeZone = nlapiLoadConfiguration('companyinformation').getFieldText('timezone');
var timeZoneOffSet = (companyTimeZone.indexOf('(GMT)') == 0) ? 0 : new Number(companyTimeZone.substr(4, 6).replace(/\+|:00/gi, '').replace(/:30/gi, '.5'));
var UTC = currentDateTime.getTime() + (currentDateTime.getTimezoneOffset() * 60000);
var companyDateTime = UTC + (timeZoneOffSet * 60 * 60 * 1000);
return new Date(companyDateTime);
}
It uses your company's NetSuite settings and timezone. This will return the date in the correct timezone assuming your NetSuite settings are correct.
You could then essentially do:
function currentDate(addDays) {
if (addDays == null||addDays == undefined) {
addDays = 0;
}
var currentdate = getCompanyDate();
var current = nlapiAddDays(currentdate,addDays);
var day = current.getDate();
var month = current.getMonth()+1
var year = current.getFullYear();
return day+'/'+month+'/'+year;
}
Suitescript 2.0 version of #lez-yeoh getCompanyDate
function getCompanyDate(){
var currentDateTime = new Date();
var companyTimeZone = config.load({ type: config.Type.COMPANY_INFORMATION }).getText({ fieldId: 'timezone' });
var timeZoneOffSet = (companyTimeZone.indexOf('(GMT)') == 0) ? 0 : Number(companyTimeZone.substr(4, 6).replace(/\+|:00/gi, '').replace(/:30/gi, '.5'));
var UTC = currentDateTime.getTime() + (currentDateTime.getTimezoneOffset() * 60000);
var companyDateTime = UTC + (timeZoneOffSet * 60 * 60 * 1000);
return new Date(companyDateTime);
}
This is what I do but you consume usage units since you have to create record.
First I create a hidden custom Date/Time field. Then I use the following code.
var record = nlapiCreateRecord(<recordtype>);
record.setDateTimeValue(<fieldid>, nlapiDateToString(new Date(), 'datetimetz', 5);
var userDateTime = record.getFieldValue(<fieldid>);
The variable userDateTime should now be in the local time zone.
The nlapiSetDateTimeValue() API function will convert the date/time value to the user's timezone. Below is its syntax:
nlapiSetDateTimeValue(fieldId, dateTime, timeZone)
fieldId = Id of the date/time field.
dateTime = Date value to be converted.
timeZone = The timezone of the date being passed. If its a server side script, it is usually in Pacific so we pass the Olson value of 5.

Time difference in Nodejs?

Im trying to figure out a way to get the time difference in seconds between two dates.
For example, difference in seconds between:
2013-5-11 8:37:18
2013-5-11 10:37:18
Tried:
function timeDifference(laterdate, earlierdate) {
var difference = laterdate.getTime() - earlierdate.getTime();
var daysDifference = Math.floor(difference/1000/60/60/24);
difference -= daysDifference*1000*60*60*24
var hoursDifference = Math.floor(difference/1000/60/60);
difference -= hoursDifference*1000*60*60
var minutesDifference = Math.floor(difference/1000/60);
difference -= minutesDifference*1000*60
var secondsDifference = Math.floor(difference/1000);
return secondsDifference;
}
But that does not work in Nodejs, error with
getTime()
function not being found
var moment = require('moment')
var startDate = moment('2013-5-11 8:73:18', 'YYYY-M-DD HH:mm:ss')
var endDate = moment('2013-5-11 10:73:18', 'YYYY-M-DD HH:mm:ss')
var secondsDiff = endDate.diff(startDate, 'seconds')
console.log(secondsDiff)
You will need the moment.js module
npm install -S moment
The timezonecomplete module has support for date differences, even with dates in different time zones. It returns a Duration object which is unit-aware, not just a "number" that represents "milliseconds":
var tc = require("timezonecomplete");
var start = new tc.DateTime("2014-06-26T12:00:00 Europe/Amsterdam");
var end = new tc.DateTime("2014-06-26T12:00:00 UTC");
var duration = end.diff(start); // unit-aware duration
console.log(duration.minutes()); // -120
console.log(duration.hours()); // -2
It will check the system time and find the difference.
var moment = require('moment')
var firstTime = moment();
setInterval(someTask,1000);
function someTask(){
var secondTime = moment();
var timeDifference = secondTime.diff(firstTime, 'seconds')
console.log(timeDifference)
}`
If you just want to set timeout on a loop as I did, you don't need to use momentjs at all. Try the following.
let timeout = 3; //seconds
console.log("start:" + new Date());
let start = Number(Date.now());
let end = start + timeout * 1000;
while (Number(Date.now()) < end) {
// your code here
}
console.log("end:" + new Date());
PS: I understand that this post does not quite answer the question asked, but this is the link popping up when you google 'time difference in nodejs'.
Get the remaining days :
var moment = require('moment');
var startDate = moment(new Date()).format("YYYY-MM-DD");
var endDate = moment(new Date("Tue Aug 27 2015 09:13:40 GMT+0530 (IST)")).format("YYYY-MM-DD");
var remainingDate = moment(endDate).diff(startDate, 'days');
console.log(remainingDate) // at time of posting, 106 days
We can use this optimized code too,
function calculateDays(startDate,endDate)
{
var start_date = moment(startDate, 'YYYY-MM-DD HH:mm:ss');
var end_date = moment(endDate, 'YYYY-MM-DD HH:mm:ss');
var duration = moment.duration(end_date.diff(start_date));
var days = duration.asDays();
return days;
}
Here you need to install moment and want to import before using.
Moment.js
const MOMENT = require('moment');
const TimeDiff = ( startTime, endTime, format ) => {
startTime = MOMENT( startTime, 'YYYY-MM-DD HH:mm:ss' );
endTime = MOMENT( endTime, 'YYYY-MM-DD HH:mm:ss' );
return endTime.diff( startTime, format);
}
let startTime = new Date('2013-5-11 8:37:18');
let endTime = new Date('2013-5-11 10:37:18');
console.log( TimeDiff(startTime, endTime, 'seconds'));

Resources