Reputation: 1427
How do I query for a date field in MongoDB with the date only, and not times? For example, if MongoDB stores July 7, 2015 with any time, I want to match that day only with today's date.
In MySQL, I would do SELECT col1, col2 FROM table WHERE DATE(date_field) = DATE(NOW());
Notice how MySQL has a function to change the date_field to the date only during matching. Can I do this in MongoDB with a similar function during matching? Like Collection.find({ dateonly(datetimefield): dateonly(new Date() });
or something of the like?
I understand Mongo stores date/times in GMT, so I would also have to convert the stored GMT date+time from GMT to Local before matching the date only, but to get me started, would like to know if I can strip the time off of a date match. For example, if GMT now is July 8 at 03:00 but Local Eastern Time US is July 7 at 23:00 then I would want to match July 7.
Upvotes: 42
Views: 95504
Reputation: 1427
Updated 2018-06-26 fixed up the code to use moment() instead of new Date()
I solved this by use MomentJS Timezone (http://momentjs.com/timezone/) to convert a local date/time to a date-only numerical field, then I store the date as a number.
In my javascript code (outside of MongoDB):
var localDateOnly = function(timezone, d) {
if (d == undefined) { d = new Date(); } // current date/time
return Number( moment(d).tz(timezone).format("YYYYMMDD") );
}
Then I store a date-only field in the Mongo record.
var myDate = localDateOnly("America/New_York"); // today, in YYYYMMDD number
db.birthdays.insert(
{ dateonly: myDate, event: "This day is my birthday!" }
);
Then in my Javascript code, I can easily query today, tomorrow, specific days, etc.
// today
var myDate = localDateOnly("America/New_York");
db.birthdays.find( { dateonly: myDate } );
// tomorrow
var myDate = localDateOnly(
"America/New_York",
moment().add( 1, "days" )
); // tomorrow
db.birthdays.find( { dateonly: myDate } );
// someone wants to know birthdays on the calendar on July 15, 2015,
// no timezone math needed, just type the date in YYYYMMDD format
db.birthdays.find( { dateonly: 20150715 } );
Hope this helps someone. Decided to store as a number for performance and validity checking. Before insert, I check for a valid date using the moment package as well:
moment( 20150715, "YYYYMMDD", true ).isValid() // returns true & allowed to store in the database
moment( 150715, "YYYYMMDD", true ).isValid() // returns false, don't insert into db
Code was cleaner when storing integers that represented dates, and made it easy for mongo to find ranges. Like, find birthdays in 2015 would be {"$gte": 20150101, "$lte": 20151231}
or {"$gte": 20150000, "$lte": 20159999}
.
Upvotes: 9
Reputation: 662
It's possible with $expr
{ $expr: {$eq: ["2021-03-29", { $dateToString: {date: "$dateField", format: "%Y-%m-%d"}}]}}
Upvotes: 17
Reputation: 436
You can extract the date as string at any given format and compare it with your date at that format using aggregation pipiline
$addFields: { "creationDate": {$dateToString:{format: "%Y-%m-%d", date: "$createdAt"}}}},
{$match : { creationDate: {$eq: req.query.date}}
Upvotes: 18
Reputation: 3043
I guess You should make a range query between the start of the day and its ending(or without ending if you are talking about today). Something like this
db.collection.find({
"date" : {"$gte": new Date("2015-07-07T00:00:00.000Z"),
"$lt": new Date("2015-07-08T00:00:00.000Z")}
})
Upvotes: 42
Reputation: 61
This is my proposed solution:
db.collection.find({
$and: [
{"date": {$gte: new Date("2015-07-07T00:00:00.000Z")}},
{"date": {$lt: new Date("2015-07-08T00:00:00.000Z")}}
]
})
Upvotes: 6
Reputation: 4660
I did a combination of the answers of Crash_Override and Maxim_PontyUshenko. Use Moment.js and the $gt, $lt mongo operators.
ship_date: {
$lt: moment().hours(0).minutes(0).seconds(0).milliseconds(0).add(28, "days").toDate(),
$gte: moment().hours(0).minutes(0).seconds(0).milliseconds(0).toDate()
}
Upvotes: 1