MongoDB date range query - node.js

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.

Related

node js - MSSQL node module automatically converts Date as DateTime

I'm retrieving the SQL Date value from sql database using MSSQL node module through node js application but the resultant record set returns the date as Date time value.
2020-11-21 in database is displayed as 2020-11-21T00:00:00
Should we need to handle this explicitly?
This is not "DateTime", that's how toString of a Date object looks like in Javascript:
If you want it to be printed in a certain format that shows only the "date" portion, you can use toLocaleDateString():
const d = new Date()
console.log(d.toLocaleDateString()) // '11/18/2020'
or, if you want the result to be formatted like the example above: yyyy-mm-dd you can do:
d.toISOString().slice(0, 10); // '2020-11-18'

Firebase get data by timestamp

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')

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!

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.

Javascript momentjs convert UTC from string to Date Object

Folks,
Having a difficult time with moment.js documentation.
record.lastModified = moment.utc().format();
returns:
2014-11-11T21:29:05+00:00
Which is Great, its in UTC... When I store that in Mongo, it gets stored as a String, not a Date object type, which is what i want.
What I need it to be is:
"lastModified" : ISODate("2014-11-11T15:26:42.965-0500")
But I need it to be a native javascript object type, and store that in Mongo. Right now if i store the above, it goes in as string, not Date object type.
I have tried almost everything with moment.js. Their toDate() function works, but falls back to my local timezone, and not giving me utc.
Thanks!
Saving a Javascript Date object will result in an ISODate being stored in Mongo.
Saving an ISO date as a Javascript String will result in a String being stored in Mongo.
So, this is what you want: record.lastModified = new Date(moment().format());
Not an ideal solution, But I achieved the same result, by manually converting it to ISODate object through monogo shell. We need the ISODate for comparison/query for aggregating results, so we run this script before running our aggregate scripts.
Inserting local time string by using moment().format().
"createdDt" : "2015-01-07T17:07:43-05:00"`
Converting to an ISODate (UTC) with:
var cursor = db.collection.find({createdDt : {$exists : true}});
while (cursor.hasNext()){
var doc = cursor.next();
db.collection.update(
{_id : doc._id},
{$set: {createdDt : new ISODate(doc.createdDt)}})
}
results in
"createdDt" : ISODate("2015-01-07T22:07:43Z")"
Note the time got converted
T17:07:43-05:00 to T22:07:43Z
I could not find any solution for inserting BSON ISODate format (which is UTC by default) from JavaScript directly, while inserting a new document, it seems to be available through pyMongo & C#/Java Drivers though. Trying to look for an maintainable solution

Resources