Firebase get data by timestamp - node.js

I need to filter data using to get specific data for the timestamp match.
For example I need the data where arrivalTime matches with exact date and time fields, timestamp field in database.
I am trying below but it returns no data.
_arrivalTIme = moment(
`${todaysDate.format('YYYY/MM/DD')} ${_arrivalTIme}:00`,
).toDate();
// _arrivalTIme: Thu May 28 2020 09:00:00 GMT-0600 (Mountain Daylight Time)
return firestore()
.collection('mainCol')
.doc(todayDate)
.collection('subCol')
.where('arrivalTime', '==', `${_arrivalTIme}`) ...
my db record looks like this:
What am I doing wrong?

You're comparing a date field in your database with a string from your code. That comparison will never be true.
You'll either need to get a Timestamp value that is exactly the same as the value in the database, or (more commonly) do a range check:
return firestore()
.collection('mainCol')
.doc(todayDate)
.collection('subCol')
.where('arrivalTime', '>=', new Date('2020-05-28 08:00:00')
.where('arrivalTime', '<', new Date('2020-05-28 08:01:00')

Related

How truncate time while querying documents for date comparison in Cosmos Db

I have document contains properties like this
{
"id":"1bd13f8f-b56a-48cb-9b49-7fc4d88beeac",
"name":"Sam",
"createdOnDateTime": "2018-07-23T12:47:42.6407069Z"
}
I want to query a document on basis of createdOnDateTime which is stored as string.
query e.g. -
SELECT * FROM c where c.createdOnDateTime>='2018-07-23' AND c.createdOnDateTime<='2018-07-23'
This will return all documents which are created on that day.
I am providing date value from date selector which gives only date without time so, it gives me problem while comparing date.
Is there any way to remove time from createdOnDateTime property or is there any other way to achieve this?
CosmosDB clients are storing timestamps in ISO8601 format and one of the good reasons to do so is that its lexicographical order matches the flow of time. Meaning - you can sort and compare those strings and get them ordered by time they represent.
So in this case you don't need to remove time components just modify the passed in parameters to get the result you need. If you want all entries from entire date of 2018-07-23 then you can use query:
SELECT * FROM c
WHERE c.createdOnDateTime >= '2018-07-23'
AND c.createdOnDateTime < '2018-07-24'
Please note that this query can use a RANGE index on createdOnDateTime.
Please use User Defined Function to implement your requirement, no need to update createdOnDateTime property.
UDF:
function con(date){
var myDate = new Date(date);
var month = myDate.getMonth()+1;
if(month<10){
month = "0"+month;
}
return myDate.getFullYear()+"-"+month+"-"+myDate.getDate();
}
SQL:
SELECT c.id,c.createdOnDateTime FROM c where udf.con(c.createdOnDateTime)>='2018-07-23' AND udf.con(c.createdOnDateTime)<='2018-07-23'
Output :
Hope it helps you.

TimeZone proplem in sequelize

Table name like users following columns are there
*Id -------------- (int type)
*DateandTime --------(Date type)
*Name -------------(varchar type)
I already insert one row like
Id = 123
Name = MR.X
DateandTime = 2018-01-12 06:22:06
Now select query in sequelize
model.user.findAll({
attributes: ['ID','DateandTime','NAME'],
where: {ID: useId} })
.then((userResult) => {
....... })
but getting DateandTime "2018-01-12T06:22:06.000Z"
You are getting out exactly what you put in. You have inserted a row as a string and it has been converted to a UTC date, it has not been stored the same as the string you put in.
When requesting it back out again, it is returning the date you put in, but from its database date form, not the original string.
You need to either store the date string as a string (varchar) if you just want the value as-is. Or, if you need to use the date for any date related functions, when you retrieve it back to display, you need to convert it to the string value you want.
I suggest using moment.js
const stringDate = moment(date).format('YYYY-MM-DD HH:mm');

set GrapqQL date format

I have a mongoDB database in which one field is an ISO date.
When i query the table using a graphql (node) query i receive my objects back all right but the date format i see in graphiql is in this weird format:
"created": "Sun Nov 26 2017 00:55:35 GMT+0100 (CET)"
if i write the field out in my resolver is shows:
2017-11-25T23:55:35.116Z
How do i change the date format so it will show ISO dates in graphiql?
the field is just declared as a string in my data type.
EDIT
My simple type is defined as:
type MyString {
_id: String
myString: String
created: String
}
When I insert a value into the base created is set automatically by MongoDB.
When I run the query it returns an array of obejcts. In my resolver (for checking) I do the following:
getStrings: async (_, args) => {
let myStrings = await MyString.find({});
for (var i = 0; i < myStrings.length; i++) {
console.log(myStrings[i]["created"]);
}
return myStrings;
}
all objects created date in the returned array have the form:
2017-11-25T23:55:35.116Z
but when i see it in GraphIql it shows as:
"created": "Sun Nov 26 2017 00:55:35 GMT+0100 (CET)"
my question is: Why does it change format?
Since my model defines this as a String it should not be manipulated but just retain the format. But it doesn't. It puzzels me.
Kim
In your resolver, just return a formatted string using toISOString()
const date1 = new Date('2017-11-25T23:45:35.116Z').toISOString();
console.log({date1});
// => { date1: '2017-11-25T23:45:35.116Z' }
const date2 = new Date('Sun Nov 26 2017 00:55:35 GMT+0100 (CET)').toISOString();
console.log({date2})
// => { date2: '2017-11-25T23:55:35.000Z' }
UPDATED to answer the added question, "Why does [the date string] change format"?
Mongo does not store the date as a string. It stores the date as a Unix epoch (aka Unix time, aka POSIX time), which is the number of seconds that have elapsed since January 1, 1970 not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). Since your data model requests a string, it'll coerce the value using toString()
const date1 = new Date('2017-11-25T23:45:35.116Z').toString();
console.log({date1})
// => { date1: 'Sat Nov 25 2017 15:45:35 GMT-0800 (PST)' }
That should clarify the behavior for you, but what you probably really want to do is change your model so that created is properly typed as a Date. You can do this a couple ways.
Create a custom scalar
GraphQLScalarType
Creating custom scalar types
Or use an existing package that already does the above for you
graphql-date
graphql-iso-date
You just need to do step by step:
Set type of your field is Object
Insert line scalar Object into your .graphql file
Add dependence graphql-java-extended-scalars into pom.xml file
Add syntax .scalar(ExtendedScalars.Object) in buildRuntimeWiring function
Let try it.
I try it and successful!

MongoDB date range query

I am using node.js and Mongo DB in my application.
I have stored date in a field(datetime) of an entry in a MongoDB as:
db.collection('person').insertOne({"name": "ABC","age": "40","datetime": Date()}
This outputs date as:"datetime":"Mon Nov 21 2016 00:47:39 GMT-0500 (Eastern Standard Time)"
Now I am trying to find all entries which are greater than a particular date.
For this I do the following:
db.collection('person').find( {'datetime':{$gt: startingdate})
where startingdate contains 22,11,2016.
This doesn't work and fetches me all the records that have a datetime field.
I even tried using :
startingdate = Date(22,11,2016)
and
startingdate = Date(2016,11,22)
but to no avail. Can someone help me figure this out?
Thanks!
Use new Date() instead of Date().
new Date() returns date object whereas Date() returns string representation of datetime.
You need to send date object to MongoDB so that it can transform the date object to ISODate.

MomentJS getting JavaScript Date in UTC

I am not able to get the JavaScript Date string for MongoDB record via the following. It keeps using my local time.
var utc = moment.utc().valueOf();
console.log(moment.utc(utc).toDate());
Output:
Tue Nov 11 2014 14:42:51 GMT-0500 (EST)
I need it to be in UTC, so I can stick this timestamp in Mongo so type would be Date.
How can I do that?
A timestamp is a point in time. Typically this can be represented by a number of milliseconds past an epoc (the Unix Epoc of Jan 1 1970 12AM UTC). The format of that point in time depends on the time zone. While it is the same point in time, the "hours value" is not the same among time zones and one must take into account the offset from the UTC.
Here's some code to illustrate. A point is time is captured in three different ways.
var moment = require( 'moment' );
var localDate = new Date();
var localMoment = moment();
var utcMoment = moment.utc();
var utcDate = new Date( utcMoment.format() );
//These are all the same
console.log( 'localData unix = ' + localDate.valueOf() );
console.log( 'localMoment unix = ' + localMoment.valueOf() );
console.log( 'utcMoment unix = ' + utcMoment.valueOf() );
//These formats are different
console.log( 'localDate = ' + localDate );
console.log( 'localMoment string = ' + localMoment.format() );
console.log( 'utcMoment string = ' + utcMoment.format() );
console.log( 'utcDate = ' + utcDate );
//One to show conversion
console.log( 'localDate as UTC format = ' + moment.utc( localDate ).format() );
console.log( 'localDate as UTC unix = ' + moment.utc( localDate ).valueOf() );
Which outputs this:
localData unix = 1415806206570
localMoment unix = 1415806206570
utcMoment unix = 1415806206570
localDate = Wed Nov 12 2014 10:30:06 GMT-0500 (EST)
localMoment string = 2014-11-12T10:30:06-05:00
utcMoment string = 2014-11-12T15:30:06+00:00
utcDate = Wed Nov 12 2014 10:30:06 GMT-0500 (EST)
localDate as UTC format = 2014-11-12T15:30:06+00:00
localDate as UTC unix = 1415806206570
In terms of milliseconds, each are the same. It is the exact same point in time (though in some runs, the later millisecond is one higher).
As far as format, each can be represented in a particular timezone. And the formatting of that timezone'd string looks different, for the exact same point in time!
Are you going to compare these time values? Just convert to milliseconds. One value of milliseconds is always less than, equal to or greater than another millisecond value.
Do you want to compare specific 'hour' or 'day' values and worried they "came from" different timezones? Convert to UTC first using moment.utc( existingDate ), and then do operations. Examples of those conversions, when coming out of the DB, are the last console.log calls in the example.
Calling toDate will create a copy (the documentation is down-right wrong about it not being a copy), of the underlying JS Date object. JS Date object is stored in UTC and will always print to eastern time. Without getting into whether .utc() modifies the underlying object that moment wraps use the code below.
You don't need moment for this.
new Date().getTime()
This works, because JS Date at its core is in UTC from the Unix Epoch. It's extraordinarily confusing and I believe a big flaw in the interface to mix local and UTC times like this with no descriptions in the methods.
This will give you the UTC timezone DateTime.
var convertedUtcDateTime = moment.utc(dateTimeToBeConverted);
When you call .utc(), all you're doing is setting a flag in the Moment object that says "this must format as UTC." You can see this change if you inspect the object's properties.
As another answer mentioned, the point in time remains the same. This ensures calculations etc. can be carried out without worrying about the time zone.
A JavaScript Date also stores timezone information, and similarly will format the value it represents as local or UTC depending on what method you call.
Option 1
Use the formatting methods as they were intended, and make the last thing you do before sending the value to the server a format into a UTC string.
For Moment, that's simply calling .toISOString() on any date local or otherwise, or the .format() method after calling .utc() if you want to specify a different format.
For JS dates, that's also a .toISOString() method.
If for some reason you don't have the ability to keep the dates in local time, or can't transform to a string for the data send, you have (at least) two further options:
Option 2
Use the JS Date constructor to manually create a datetime in the local timezone, pulling the components from your UTC Moment object.
let utc = moment().utc();
let date = new Date(utc.year(), utc.month(), utc.date(), utc.hour(), utc.minute(), utc.second(), utc.millisecond());
Alternatively, get the current datetime and then set the hours and minutes as appropriate for the timezone change.
You'll end up with a date representation of the UTC time marked as local time. This is not the correct time, as you're now offset by the time zone, but it might solve a problem in a pinch.
Option 3
Similar to option 2, this is another way to create an offset Date where UTC is marked as the local time zone.
Export the ISO string from either Moment or JS, strip off the Zulu flag at the end, and use the string constructor for Date to pull it back in.
new Date(new Date().toISOString().slice(0,-1));
Again, this is not actually the correct time and calculations against other datetimes may be incorrect. Your best option is still to send up a UTC ISO string to the server when you can.
Or simply:
Date.now
From MDN documentation:
The Date.now() method returns the number of milliseconds elapsed since January 1, 1970
Available since ECMAScript 5.1
It's the same as was mentioned above (new Date().getTime()), but more shortcutted version.

Resources