Between two dates - javascript

I can't figure out why the findOne function doesn't work. My code
async getSign(childrenId: number, week?: number, year?: number) {
if (week && year) {
const startDate = moment().year(year).week(week).startOf("week").format("YYYY-MM-DD");
const endDate = moment().year(year).week(week).endOf("week").format("YYYY-MM-DD");
console.log(startDate, endDate);
const signature = await this.diarySignRepository.findOne({
where: {
childrenId,
date: {
$between: [startDate, endDate]
}
},
attributes: ['sign'],
});
return signature?.sign;
}
}
My request:
http://localhost:5000/diary/sign/get/1?week=11&year=2023
In database i have record:
|id |childrenId|date |sign|
|---|----------|----------|----|
|2 |1 |2023-03-17|true|
In console i get:
2023-03-12 2023-03-18
Executing (default): SELECT "sign" FROM "diary_sign" AS "DiarySign" WHERE "DiarySign"."childrenId" = '1' AND "DiarySign"."date" = '2023-02-18' LIMIT 1;
I don't understand why between doesn't work

Your SQL is incorrect:
SELECT "sign" FROM "diary_sign" AS "DiarySign"
WHERE "DiarySign"."childrenId" = '1'
AND "DiarySign"."date" = '2023-02-18'
LIMIT 1;
Your database has 2023-03-17 whilst you're searching for 2023-02-18.
As a sanity check, remove date: { $between: [startDate, endDate] }, your SQL query will then search over childrenId, returning the expected entry.
To search dates correctly, startDate and endDate must be Date objects, whereas you're using strings, fix that. (Apply .format("YYYY-MM-DD") in console.log for pretty printing.) If that doesn't work, we'll need to see diarySignRepository.findOne.

Related

Mongoose lte method not working for moment

I am fetching Date saved in db. Then, I am doing a small date maths to substract date from today from 3, which is giving me Date in Format - (DD-MM-YYYY). Date saved in db format is also same - (DD-MM-YYYY). Can anyone help me out in validating $lte for that date. I am not getting any log for DipData.
nodeCron.schedule("* * * * *", async function () {
var DateNow = await moment().subtract(3, "days").format("DD-MM-YYYY");
console.log("Test Date Cron",DateNow);
console.log("-->",new Date(DateNow.format("DD-MM-YYYY")));
let DipData = await userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow.format("DD-MM-YYYY")) }})
console.log("-----DipData ------->", DipData);
});
First thing you need to identify if there is date which is stored in document of mongo collection is string or regular date format or epoch format. If it's string the query may gives not accurate result. If there is date format or epoch format, you can easily queried your result with proper result.
Therefore in case if there is string in LastAppOpenedTime document key you can have query with $toDate under find query.
If key is not in string format in stored document following code will work.
var DateNow = moment().subtract(3, "days");
const DipData = await userModel.find({ LastAppOpenedTime: { $lte: new Date(DateNow) } });
For the above two scenario would work if your query is in accurate form like removing the first empty braces.
userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow) }})
to
userModel.find({ LastAppOpenedTime: { $lte : new Date(DateNow) }})
Hello I got this working by making a few changes
const DateNow = await moment().subtract(3, "days");
console.log("Test Date Cron", DateNow);
console.log("-->", new Date(DateNow));
const DipData = await userModel.find({ createdAt: { $lte: new Date(DateNow) } });
console.log("-----DipData ------->", DipData);
res.status(200).json({ success: true, message: "Request was successful", DipData });
I noticed you had the .format("DD-MM-YYYY") at the end of your moment function but it returned a string that couldn't be converted with the new Date(DateNow). I removed mine when testing as the response from the moment was working fine without it.
And also I updated your userModel.find({}, { LastAppOpenedTime: { $lte : new Date(DateNow.format("DD-MM-YYYY")) }}) to remove the first empty {}. So you would have userModel.find({ createdAt: { $lte: new Date(DateNow) } });

Browser Time different from MySQL Time

I'm currently working on a NodeJS-MySQL project, I'm making a controller for a table (graduates). This table has two attributes (created_at, updated_at) that receive the current date and time. The problem is: when I GET the values from this table in the Browser/Insomnia, the date is in the UTC 0 time zone (not what I want), but when i check directly on MySQL, it is in the UTC -3 (my time zone/what i want). In order to get the date values i'm using moment.js and moment-timezone.js.
Some parts of my code:
var moment = require('moment');
var moment = require('moment-timezone');
moment().tz("America/Sao_Paulo").format();
setting up moment.js (setting the timezone to Sao_Paulo didn't change anything, probably i'm using it wrong)
const result = await mysql.execute("SELECT * FROM graduates;")
const response = {
length: result.length,
graduates: result.map(graduate => {
return {
id: graduate.id,
nomeGrad: graduate.nomeGrad,
description: graduate.description,
created_at: graduate.created_at,
updated_at: graduate.updated_at
}
})
}
Get for the table graduates (on MySQL, when I use "SELECT * FROM graduates", I get the same values, the only difference being the time)
var dateTime = moment().tz("America/Sao_Paulo").format();
try {
const query = 'INSERT INTO graduates (id, nomeGrad, description, created_at, updated_at) VALUES (?,?,?,?,?)';
const result = await mysql.execute(query, [
req.body.id,
req.body.nomeGrad,
req.body.description,
created_at = dateTime,
updated_at = dateTime
]);
And this is how I Post the graduates. Now for the outputs:
{
"id": "43",
"nomeGrad": "iiiiiiiiiiiiiiiiiiiiiii",
"description": "ssssssssssssssssssssssssss",
"created_at": "2021-10-26T23:44:10.000Z",
"updated_at": "2021-10-26T23:44:10.000Z"
}
The above output is from Insomnia / Browser (Time is 23:44)
# id, nomeGrad, description, created_at, updated_at
'43', 'iiiiiiiiiiiiiiiiiiiiiii', 'ssssssssssssssssssssssssss', '2021-10-26 20:44:10', '2021-10-26 20:44:10'
The above output is from directly typing "SELECT * FROM graduates" on MySQL (Time is 20:44)
Thank you for your time and patience for reading this.

How to find date using moment in mongoose with date type

I want to search by date type in mongo db I've a problem that when I use moment It's change my default date so I don't understand why It change my date with same code
Here is what I try
let params = {}
let date = "2020-05-27" //I send it in String Type
const newDate = new Date(date)
const start = moment(newDate).startOf('day')
const end = moment(newDate).endOf('day')
console.log(newDate)
console.log(start._d, end._d)
Object.assign(params, { updatedAt: { $gte: start, $lte: end } })
await Order.find(params)
when I send first request It's return the right date and collect defaut but after I send 1 more request my start._d change value while my date is the same value
here is my first console.log
api | 2020-05-27T00:00:00.000Z //date
api | 2020-05-27T00:00:00.000Z (start.d) 2020-05-27T16:59:59.999Z (end.d)
here is my second console.log
api | 2020-05-27T00:00:00.000Z //date
api | 2020-05-26T17:00:00.000Z(start.d) 2020-05-26T23:59:59.999Z(end.d)
as you see why my start.d -1 day while my date is same value at first time
after I send more request it will show same 2nd console.log
I still don't know why but I fix it by set all date by static
let newDate = moment(date, 'YYYY-MM-DD')
// let start = moment(newDate).startOf('day')
let start = newDate.toDate() // This will return a copy of the Date that the moment uses
start.setHours(0)
start.setMinutes(0)
start.setSeconds(0)
start.setMilliseconds(0)
let end = newDate.toDate()
end.setHours(23)
end.setMinutes(59)
end.setSeconds(59)
end.setMilliseconds(59)

Querying a timestamp by date with Sequelize

I want to find some entries in my DB through the createdAt column, but just using the date. I am using postgres and the createdAt is a timestamptz. Here is an example of what an entry in it looks like: 2019-02-27 20:17:07.05+00
This is what the setting of my query looks like:
const dateString = momentDate.format('YYYY-MM-DD')
query.createdAt = { $iLike: `%${dateString}` }
Unfortunately this is not working and I am getting the following error:
retry-as-promised:error SequelizeDatabaseError: operator does not exist: timestamp with time zone ~~* unknown
Is the issue perhaps because I am using a string? What is the right way to query by date?
Using function DateDiff to get days from between createdAt and dateString. Need to cast dateString to datetime
var sequelize = require('sequelize');
var dateString = '01/03/2019';
yourModel.findAll({
where: sequelize.literal(`DATEDIFF(day,Cast(${dateString} as datetime), createdAt) = 0`)
})
.then(results => {
})
.catch(err => {
});

Can I query MongoDB ObjectId by date?

I know that ObjectIds contain the date they were created on. Is there a way to query this aspect of the ObjectId?
Popping Timestamps into ObjectIds covers queries based on dates embedded in the ObjectId in great detail.
Briefly in JavaScript code:
/* This function returns an ObjectId embedded with a given datetime */
/* Accepts both Date object and string input */
function objectIdWithTimestamp(timestamp) {
/* Convert string date to Date object (otherwise assume timestamp is a date) */
if (typeof(timestamp) == 'string') {
timestamp = new Date(timestamp);
}
/* Convert date object to hex seconds since Unix epoch */
var hexSeconds = Math.floor(timestamp/1000).toString(16);
/* Create an ObjectId with that hex timestamp */
var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");
return constructedObjectId
}
/* Find all documents created after midnight on May 25th, 1980 */
db.mycollection.find({ _id: { $gt: objectIdWithTimestamp('1980/05/25') } });
In pymongo, it can be done this way:
import datetime
from bson.objectid import ObjectId
mins = 15
gen_time = datetime.datetime.today() - datetime.timedelta(mins=mins)
dummy_id = ObjectId.from_datetime(gen_time)
result = list(db.coll.find({"_id": {"$gte": dummy_id}}))
Using inbuilt function provided by mongodb drivers in in Node.js lets you query by any timestamp:
var timestamp = Date.now();
var objectId = ObjectID.createFromTime(timestamp / 1000);
Alternatively, to search for records before the current time, you can simply do:
var objectId = new ObjectID(); // or ObjectId in the mongo shell
Source: http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html
You can use $convert function to extract the date from ObjectId starting in 4.0 version.
Something like
$convert: { input: "$_id", to: "date" }
You can query on date comparing between start and end time for date.
db.collectionname.find({
"$expr":{
"$and":[
{"$gte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T00:00:00.000Z")]},
{"$lte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T11:59:59.999Z")]}
]
}
})
OR
You can use shorthand $toDate to achieve the same.
db.collectionname.find({
"$expr":{
"$and":[
{"$gte":[{"$toDate":"$_id"}, ISODate("2018-07-03T00:00:00.000Z")]},
{"$lte":[{"$toDate":"$_id"},ISODate("2018-07-03T11:59:59.999Z")]}
]
}
})
how to find Find the Command (this date[2015-1-12] to this Date[2015-1-15]):
db.collection.find({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
}).pretty()
Count the Command (this date[2015-1-12] to this Date[2015-1-15]):
db.collection.count({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
})
Remove the Command (this date[2015-1-12] to this Date[2015-1-15]):
db.collection.remove({
_id: {
$gt: ObjectId(Math.floor((new Date('2015/1/12'))/1000).toString(16) + "0000000000000000"),
$lt: ObjectId(Math.floor((new Date('2015/1/15'))/1000).toString(16) + "0000000000000000")
}
})
Since the first 4 bytes of an ObjectId represent a timestamp, to query your collection chronologically, simply order by id:
# oldest first; use pymongo.DESCENDING for most recent first
items = db.your_collection.find().sort("_id", pymongo.ASCENDING)
After you get the documents, you can get the ObjectId's generation time like so:
id = some_object_id
generation_time = id.generation_time
Yes you can query object by date using MongoDB inserted ID
db.collectionname.find({_id: {$lt: ObjectId.fromDate( new ISODate("TZformat") ) } });
let's suppose users is my collection and I want all users created less than 05 January 2018
db.users.find({_id: {$lt: ObjectId.fromDate( new ISODate("2018-01-05T00:00:00.000Z") ) } });
For running from a query we can use like
db.users.find({_id: {$lt: ObjectId.fromDate(new Date((new Date().getTime() - (1 * 3 * 60 * 60 * 1000))) ) } })
All the users from the current time - 3 hours
To get last 60 days old documents in mongo collection i used below query in shell.
db.collection.find({_id: {$lt:new ObjectId( Math.floor(new Date(new Date()-1000*60*60*24*60).getTime()/1000).toString(16) + "0000000000000000" )}})
If you want to make a range query, you can do it like in this post. For example querying for a specific day (i.e. Apr 4th 2015):
> var objIdMin = ObjectId(Math.floor((new Date('2015/4/4'))/1000).toString(16) + "0000000000000000")
> var objIdMax = ObjectId(Math.floor((new Date('2015/4/5'))/1000).toString(16) + "0000000000000000")
> db.collection.find({_id:{$gt: objIdMin, $lt: objIdMax}}).pretty()
From the documentation:
o = new ObjectId()
date = o.getTimestamp()
this way you have date that is a ISODate.
Look at
http://www.mongodb.org/display/DOCS/Optimizing+Object+IDs#OptimizingObjectIDs-Extractinsertiontimesfromidratherthanhavingaseparatetimestampfield.
for more information
Using MongoObjectID you should also find results as given below
db.mycollection.find({ _id: { $gt: ObjectId("5217a543dd99a6d9e0f74702").getTimestamp().getTime()}});
A Solution Filtering within MongoDB Compass.
Based on versions:
Compass version: 1.25.0
MongoDB version: 4.2.8
Option 1:
#s7vr 's answer worked perfectly for me. You can paste this into the Filter field:
{$expr: { $and: [ {$gte: [{$toDate: "$_id"}, ISODate('2021-01-01')]}, {$lt: [{$toDate: "$_id"}, ISODate('2021-02-01')]} ] } }
Option 2:
I also found this to work (remember that the Date's month parameter is 0-based indexing so January is 0):
{_id: {$gte: ObjectId(Date(2021, 0, 1) / 1000), $lt: ObjectId(Date(2021, 1, 1) / 1000) } }
Option 3:
Equivalent with ISODate:
{_id: {$gte: ObjectId(ISODate('2021-01-01') / 1000), $lt: ObjectId(Date('2021-02-01') / 1000) } }
After writing this post, I decided to run the Explain on these queries. Here's the skinny on performance:
Option 1: 39 ms, 0 indexes used, 30 ms in COLLSCAN
Option 2: 0 ms, _id index used
Option 3: 1 ms, _id index used, 1 ms in FETCH
Based on my rudimentary analysis, it appears that option 2 is the most efficient. I will use Option 3, personally, as it is a little cleaner to use ISODate rather than remembering 0-based month indexing in the Date object.
In rails mongoid you can query using
time = Time.utc(2010, 1, 1)
time_id = ObjectId.from_time(time)
collection.find({'_id' => {'$lt' => time_id}})

Categories

Resources