MongoDB Date.now() format different from new Date(string) format - javascript

I'm struggling to understand the logic behind MongoDB date formatting, if I save a field like so:
date: Date.now()
in the database looks like:
date: 1633186879027
I have a date like 2021-08-27T19:00:38.000+00:00 , and I save it like so:
date: "2021-08-27T19:00:38.000+00:00"
in the database looks like:
date: "2021-08-27T19:00:38.000+00:00"
and it's not what I want cause it's a string and I can't sort stuff by date then.
so i tried to save it like so:
date: new Date("2021-08-27T19:00:38.000+00:00")
and in the database looks like:
date: 2021-08-27T19:00:38.000+00:00
without brakets, as Mongodb does for strings, so must not be a string either
how am I supposed to save it so that it looks like the first one (1633186879027)?
because I then need to sort stuff by date and I think that's the correct format to use?

MongoDB stores data using BSON. The definition is here
A datetime is stored as the number of milliseconds since 1970-01-01 using a 64-bit integer.
Date.now() returns an integer, so the sample data would be stored as BSON type \x12 with the value 1633186879027.
new Date("2021-08-27T19:00:38.000+00:00") would be stored as BSON type \x09 with the value 1630090838000.
The output date: 2021-08-27T19:00:38.000+00:00 was generated by the driver or application on the client side after it was retrieved.
MongoDB directly support sorting on dates.
Also note that if you have dates stored as strings like "2021-08-27T19:00:38.000+00:00", a lexicographical sort of those string would put them in chronological order.

Related

Mongodb date value to javascript string how to convert?

I logged out the value stored in one of the documents(or notes in my case) in the date key, like this
console.log(notes[0].date)
The output that I got was
and when methods like getDate() or toDateString() didn't work, what should i be doing?
You will need to convert it into a javascript date object using new Date("your mongodb date string");
See: https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Date for more infomation
If your dates are stored using the date data type you should manipulate them as data object in your code.
If your dates are not stored using the date data type you should migrate your data to store the date as date data type rather than string.
You then format the date, using the user’s LOCALE, only when you present it to the user.

Mongo query json object with dates

I try to dynamically create a mongo query with dates.
This is a part of a JSON query I produced:
{"$or":[{"createdAt":{"$gte":"2017-08-31T22:00:00.000Z"}},{"modifiedAt":{"$gte":"2017-08-31T22:00:00.000Z"}}]}
but it does not work.
This is a part of code which stands behind it:
let result = {$or: [{createdAt: {$lte: new Date(date)}}, {modifiedAt: {$lte: new Date(date)}}]};
Spent 3 hours trying to find a solution. My understanding is that $lte here tries to compare mongo date object with a string describing date in ISO format. And it does not work well.
I do not know how to create a proper JSON object being a mongo query containing dates.
Please help! :-)
If you want to query Mongo with date range, you have to use a standard Date format (ISO-8601). To achieve this, try with moment:
let date ="2019-02-22"; //for example, in my apis, you can set multiple type of date (YYYY-MM-DD, YYYYMMDD, DD-MM-YYYY,..) but date format with / is forbidden.
let query = {$or:[{createdAt: {$lte: moment(date).format()}}, {modifiedAt:{$gte: moment(date).format()}}] //pass parameter to format, in this case it will use the default locale format
Like this you are setting a query. IMO querying on date range with "OR" condition is not useful: usually a date query in is "AND" condition (if you are querying on a single date, your query will be: greater than today or lower than today -> everything)

To clear up some doubts about moment.js

I got stuck in my project, due to some doubts related to moment.js. I'll state some conclusions here I made during writing backend on project, and please can someone correct me if something is wrong?
For example, if I get datetime string from fronted, in format:
"THU 18 MAR 2017 09:20 AM", I should create moment object passing this string to it and corresponding token "ddd DD MMM YYYY HH:mm A" as passed string is not in standard ISO 8601 format.
var datetime = moment(datetimeFromFrontend, "ddd DD MMM YYYY HH:mm A");
Now I have moment object that can be formated in way I want, calling format() function on moment object.
If I want to do some manipulations with datetime generally (for example, compare to today's datetime, or compare only time part), is it mandatory to convert all manipulating datetimes, times or whatever to moment object with same format and using isBefore, isEqual and so on, or can I somehow compare them using >, <, <=, =< ?
If I need to compare (>, < etc) datetime or just time part with value retrieved from SQL database (which is DATETIME or TIME data type), should I pass both comparing values to moment object, convert them in same format and then do manipulations?
And how to save to SQL database column which is DATETIME, or TIME type? Should do some transforms from moment object to string using format()? SQL will automatically convert passing string to corresponding data type?
Example:
var now = moment();
I assume that "now" can't be passed to sql query directly as it is moment object, it should be converted to string (and rely on SQL automatic conversion from string/nvarchar to datetime) or should I save it as moment().toDate() ?
If I need to compare (>, < etc) datetime or just time part with value retrieved from SQL database (which is DATETIME or TIME data type), should I pass both comparing values to moment object, convert them in same format and then do manipulations?
You might want to lookup the docs for that
You have Query functions that can compare moments and even Date objects, for example, this is the entry for the .after function
moment().isAfter(Moment|String|Number|Date|Array);
as you can see, you can pass anything to .isAfter and it will do that job for you
moment().isAfter(new Date(2017, 2, 4))
// true
moment(new Date(2016, 2, 4)).isAfter(new Date(2017, 2, 4))
// false
Of course the easiest way to compare >, < or === is to get the timestamp using Date::getTime, but that's ugly code
And how to save to SQL database column which is DATETIME, or TIME type? Should do some transforms from moment object to string using format()? SQL will automatically convert passing string to corresponding data type?
I think it depends how you SQL works and how your server communicates to it, ORACLE, you should refer to any documentation about storing date objects inside your sql, eventually dates and formats are all about making unix-timestamps human readable/understandable.
I assume that "now" can't be passed to sql query directly as it is moment object, it should be converted to string (and rely on SQL automatic conversion from string/nvarchar to datetime) or should I save it as moment().toDate() ?
Ask yourself what kind of benefits you or anyone that may use you API will gain from getting agnostic Date objects from your DB rather then just plain strictly formatted strings?

How can I convert my normal timestamp into a BSON timestamp?

I am using https://www.npmjs.com/package/mongodb
mongodb has turned my timestamp into BSON (I know this is normal)
my timestamp is this 641912491 where as in the database it looks like this 1457904327000.000000.
I have a document with a key named date_in_the_past which holds my timestamp in it's BSON form.
Note: I am fully aware that the mongodb _id key holds a date but it is of no use to me in this scenario as, that would be the date when the document was written to the db (not the date in the past that I am looking for)
How can I convert my normal timestamp into a BSON timestamp?
I have tried to understand mongodb/js-bson and mongodb/js-bson/blob/master/lib/bson/timestamp.js but I can't see how to do it.
example of what I am looking to do:
var past=timestampToBSON(641912491);
db.collection('docs').find({date_in_the_past:past}).limit(1).toArray(function(e,r){});
If it's stored as a bson timestamp object, you could do something like this
var Timestamp = require('mongodb').Timestamp;
var past = Timestamp(641912491,1);
db.collection('docs').find({date_in_the_past:past})
or
db.collection('docs').find({date_in_the_past: Timestamp(641912491,1)})
it has some more info and examples about it here
https://docs.mongodb.org/manual/reference/bson-types/#timestamps

couchdb date format automatically updated

Whenever I update any key in couchdb document, it updates existing all date keys in milliseconds formats.
Example:
created_at: 2013-07-09T09:25:00
to
created_at: /Date(1373354700000)/
do you ever come across this issue?
The reason of this conversion can be find here.
If you're using JavaScriptSerializer then it converts the DateTime object as the format
/Date(ticks)/
But It will not convert DateTime string to ticks.
Whereas, if you're using JsonSerializer then you will find the date and time in correct format no matter of object or string type.
Note: JavaScriptSerializer is too slow in as compared to JsonConvert. You can have performance comparison of different serialization.

Categories