Create a document and set the date - Mongoose - javascript

I'm trying to create a document in mongo with a field date: Date.
When I post to API, the document created has a different time that I set, as follows:
{
"serialnumber": "1234567",
"date": "2019-08-30T10:32"
}
Result:
{
"troubles": [],
"_id": "5c35e9c8e726822a243936a9",
"serialnumber": "1234567",
"date": "2019-08-30T13:32:00.000Z",
"updated": "2019-01-09T12:32:08.996Z",
"__v": 0
}
My mongoose Schema:
var MeasurementSchema = new Schema({
serialnumber: String,
date: Date
......
As we saw, I wrote 'T10:32', but, the time of parameter 'date' results in 12:32.
Any tips?

MongoDB stores times in UTC by default, and will convert any local time representations into this form.
Applications that must operate or report on some unmodified local time value may store the time zone alongside the UTC timestamp, and compute the original local time in their application logic.
Example
In the MongoDB shell, you can store both the current date and the current client’s offset from UTC.
var now = new Date();
db.data.save( { date: now,
offset: now.getTimezoneOffset() } );
You can reconstruct the original local time by applying the saved offset:
var record = db.data.findOne();
var localNow = new Date( record.date.getTime() - ( record.offset * 60000 ) );

Related

There is no calibration between MongoDB UTC time and local time

Data is stored and inquired through the API on the web page, and the API is using MongoDB.
The server space has been unified to UTC time so that the same results can be achieved in different time zones.
MongoDB uses the Mongoose schema as follows:
const userSchema = new Schema({
userId : {
type : String
},
score : {
type : Number
},
createdAt : {
type : Date,
default : Date.now
}
});
Because Date.now in the schema is in the createdAt field by default, it does not pass the Date value separately when querying the create or update of mongoose.
Considering the case where offset exists based on UTC time, the time is calculated using moment.js as follows:
// -540 offset value for KST 9 hours faster than UTC
const utc= moment.utc().add(offset, 'm').format('YYYY-MM-DDTHH:mm:ssZ');
let beginDate = new Date(utc);
let endDate = null;
let year = beginDate.getFullYear();
let month = beginDate.getMonth();
let date = beginDate.getDate();
// To view the full duration of the day
beginDate = new Date(new Date(year, month, date).setHours(0, 0, 0, 0));
endDate = new Date(new Date(year, month, date).setHours(23, 59, 59, 59));
// Find document
const user = await userSchema.aggregate([
{
$unwind : 'lists'
},
{
$match : {
'lists.createdAt' : {
$gte : beginDate,
$lte : endDate
}
}
},
...
]);
For example, if you make a query in Korea, the data inquiry may differ from the time after midnight and to 9 a.m. the next day.
What is wrong with the above parallax correction logic? I don't exactly understand the current problem.
Why so difficult? Simply use
{
$match : {
'lists.createdAt' : {
$gte : moment().startOf('day').toDate(),
$ltr : moment().endOf('day').toDate()
}
}
}
moment().startOf('day').toDate() returns the begin of current day in your local time zone. I live in Switzerland, thus it returns ISODate("2023-01-17T23:00:00.000Z")
But you can specify also a time zone, e.g.
moment.tz('Asia/Seoul').startOf('day').toDate();
ISODate("2023-01-17T15:00:00.000Z")
The problem is moment.utc().add(...) really modifies the time value. But that is not what you need to do, you like to change only the way how the time is displayed in your local time zone.
For comparison and calculations, the displayed value does not matter. All methods are done in UTC time only.

explain MongoDB date format

For defining a model in node.js I am using mongoose library and I want to store the date in that.
here is the schema:
availability: [
{
day: {
type: String,
},
startTime: {
type: Date,
},
endTime: {
type: Date,
},
},
]
I am passing the value from postman like below:
{
"parkingId":"62cfa09adb8bc68f045b4d65",
"day":"Monday",
"startTime":7,
"endTime": 22
}
But it is getting saved like this from 1970. I am aware that passing a time like this will calculate time from Unix epoch But I want to save today's date or date passed by merchant user for availability
day:Monday,
startTime: ISODate("1970-01-01T00:00:00.007+00:00"),
endTime: ISODate("1970-01-01T00:00:00.022+00:00")
And also what is 007+00:00 or 022+00:00?
Should I use moment library for that?
This is unrelated to MongoDB, this is a mongoose feature.
You define startTime and endTime as Date in your schema, but you are passing a number. let's see what the mongoose code does in this scenraio:
function castDate(value) {
...
let date;
if (value instanceof Number || typeof value === 'number') {
date = new Date(value);
}
...
};
As you can see in the case the input value is a number which is the case here, the mongoose schema casts this value to date using js new Date() function which is basically:
JavaScript Date objects represent a single moment in time in a platform-independent format. Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.
This means when it casts new Date(7) the result is 1 January 1970 UTC + 7 mili seconds whichi is the 7 your seeing in the result 1970-01-01T00:00:00.007+00:00
Clearly in your case all you need to do is change the Date type to Number which is actually what you're trying to save.

Using ISODate with mongodb query and node.js

I am creating a string -
queryString - {"Project": "Serenity","DateOfWalkin": {"$gte": "2022-03-01" ,"$lt": "2022-03-31"} }
then parsing it - queryObject = JSON.parse( queryString )
It is parsing successfully, but when I run the query it does not give me any result.
Now when I update the same query by using ISODate for both dates, and then tried running the query in Mongo compass, it works fine.
I want to use ISODate() but the problem is the way I am building the queryString is based on different conditions from the user input, now if a particular condition is true then and only then I want to query that particular field. For other fields I am searching, which are of type "String" in my db, I am able to get the correct result, but for date I am facing this issue.
startDate and endDate are user inputs using date picker in HTML
TRIAL number 1
queryString = queryString + ,"DateOfWalkin": {"$gte": ISODate("${startDate}")} ,"$lt": { "$date" : ISODate("${endDate}") } }
This will give a parser error saying identifier "I" not found, hence I am not able to parse this string.
To combat this, I tried to use new Date object, tried to convert the date using toISOString, but it didn't work.
TRIAL number 2
queryString = queryString + ,"DateOfWalkin": {"$gte": "ISODate("${startDate}")"} ,"$lt": { "$date" : "ISODate("${startDate}")" } }
If we use double quotes for ISODate as well, it will solve the parser issue but Mongo query will not give any result and it is treating ISODate wrapper as a string literal.
TRIAL number 3
queryString = queryString + ,"DateOfWalkin": {"$gte": "${startDate}"} ,"$lt": { "$date" : "${endDate}" } }
Does not give result
TRIAL number 4
Using new Date() to get the ISODate format
Query becomes -
{
Project: 'Serenity',
DateOfWalkin: {
'$gte': 'Tue Mar 01 2022 05:30:00 GMT+0530 (India Standard Time)',
'$lt': 'Thu Mar 31 2022 05:30:00 GMT+0530 (India Standard Time)'
}
}
Still it doesn't give any result
TRIAL number 5
Query object -
{
Project: 'Serenity',
DateOfWalkin: {
'$gte': { '$date': '2022-03-01' },
'$lt': { '$date': '2022-03-01' }
}
}
Above doesn't give result
Is there any way I can store the value of ISODate("${startDate}") and use that variable in the main queryString?
Or is there a better way to compare dates when I am using the input dates as user input?
I have tried multiple approaches and kinda feeling stuck at this point.
Why do you parse the string?
Apart from your current problem, you also open the door for NoSQL-Injection. You can compose the query object also directly like this:
const queryObject = {};
queryObject["Project"] = "Serenity";
queryObject["DateOfWalkin"] = { $gte: ISODate("2022-03-01"), ["$lt"]: ISODate("2022-03-31") };
const ninDates = [];
ninDates.push(ISODate("2022-03-10"));
ninDates.push(ISODate("2022-03-20"));
queryObject["DateOfWalkin"]["$nin"] = ninDates;
db.collection.find(queryObject)
If you really insist to parse the string, then use ejson
EJSON.parse('{ "Project": "Serenity", "DateOfWalkin": { "$gte": { "$date": "2022-03-01" }, "$lt": { "$date": "2022-03-01" } } }')
Should give desired queryObject. Note, keys and values need to be enclosed by double-quotes (")

date time is changing depending on environment

I am trying to get a range of all the days within the month (eg) January 1 - January 31 2020.
This part works however, after I do .toISOString() on the Date object the date is getting changed in the browser Chrome but not in a Node application
they are doing the same code which is:
function dateFormat(month, year) {
const startDate = new Date(year, month, 1)
console.log('startDate', startDate)
const endDate = new Date(year, startDate.getMonth() + 1, 0)
console.log('endDate', endDate)
const dto = {
monthYear: {
startDate: startDate.toISOString(),
endDate: endDate.toISOString()
}
}
console.log('dto before stringify', dto)
console.log('dto', JSON.stringify(dto))
}
dateFormat(0, 2020)
what I would like is an JSON object that looks like this:
{
"monthYear": {
"startDate": "2020-01-01T00:00:00.000Z",
"endDate": "2020-01-31T00:00:00.000Z"
}
}
The Date function basically follows the environment in which it runs.
The browser returns a function corresponding to your region,
Typically, the server returns the utc time
For this reason, the global service manages the time in utc on the server, and displays the time in the local time at the front (browser) received.

Saving a String in MongoDB as a date saves wrong values

I am trying to save a string in MongoDB as a date but having hard times for storing the right values.
In Mongoose schema data value is stored as Date, however, I pass the value to data as new Date("MM-dd-YYYY") but when I look up in the database the value is transformed to this format ISODate("YYYY-MM-dd-1T21:00:00Z")
The format wouldn't bother me if the date would be the same but as you notice the value in the database is one day earlier then the value which I want to be.
So instead of 2018-09-20 is 2018-08-19. My guess is that default UTC time is not the same or something like that but how can I set the correct UTC time?
Edit:
var mongoose = require('mongoose')
var dateformat =require('moment');
//Schema
var ReservationSchema = mongoose.Schema({
name : {
type:String,
required : true,
},
numberOfGuests : {
type : Number ,
required : true,}
,
email: {
type : String,
required:true,
},
phone: {
type : String,
required:true,
},
data:{
type:Date,
require:true,
},
timetables:{
type:String,
require:true,
},
furtherRequests: {
type : String,
}
});
var reservvar = module.exports = mongoose.model('Rezervari', ReservationSchema ,'Rezervari');
module.exports.createReservation = function (query,callback){
//query.data = dateformat.utc(query.data).format("MM-DD-YYYY")
reservvar.create(query,callback);
}
module.exports.getReservations = function (callback){
reservvar.find({},callback);
}
Index.js file :
app.get('/api/reservations',function(req,res) {
Rezervari.getReservations(function(err,reserv){
if(err){
throw err;
}
var changetime = reserv[1].data;
console.log(reserv[1].data)
changetime = dateformat.utc(changetime).format("MM-DD-YYYY") // this one returns the date in desired format but with wrong values as stored in db
console.log(changetime)
res.json(reserv);
});
});
app.post('/api/createrezervare', function (req,res) {
const reserv = req.body
const name = reserv.name
const numberofg = reserv.number
const phone = reserv.phone
const email = reserv.email
const data = reserv.date
const timetable = reserv.time
const furtreq = reserv.frequests
Rezervari.createReservation({name:name,numberOfGuests:numberofg,phone:phone,email:email,data:data,timetables:timetable,furtRequests:furtreq},function(err,reserv){
if(err){
throw err}
res.json({status:true})
})
})
You are inserting a Javascript Date Object from Node.js, and that same Date is being inserted in MongoDB, it's being inserted correctly.
I think you are confusing how dates are stored internally and how are they formatted when you print them.
When you check the content of your data in MongoDB it's just shown in that particular format, an ISO date. If you take a close look at the date shown you can see a Z a the end, Z means "zero hour offset" also known as "Zulu time" (UTC).
In Javascript when you create a Date object without setting the timezone, it's by default created in your system timezone. Also, Date objects are not stored with any format, nor in JS nor in MongoDB. In JS, dates are stored internally as time values (milliseconds since 1970-01-01).
Supposing we are in Japan, JST time (UTC+9):
const d = new Date("09-20-2018");
console.log(d.getTime()); // 1537369200000
console.log(d.toString()); // Thu Sep 20 2018 00:00:00 GMT+0900 (JST)
console.log(d.toISOString()); // 2018-09-19T15:00:00.000Z
First we are printing out the number of ms, after the Date including the timezone, and finally the ISO Date, almost same format that MongoDB uses to print dates in the Mongo shell (anyway, in UTC).
So, new Date("09-20-2018") is going to store the milliseconds until 09-20-2018 00:00 in Japan Time. Then, if you insert that object in MongoDB, internally it will store the correct date (I don't know internal details of MongoDB, but maybe it's storing the milliseconds as well).
If you check MongoDB you will see something like ISODate("2018-09-19T15:00:00Z").

Categories