Problem with timezones in pymongo/mongodb - mongodb

I have this function which parses the dates in my database
def parserQuestions():
res=db.questionsActual.find({'date_created':{'$type':'string'}})
for doc in res:
db.questionsActual.update_one({'_id': doc.get('_id')}, {'$set': { 'date_created': parse(doc.get('date_created'))}})
My input format is:
2020-12-11T13:23:58.677-04:00
but when I apply the function, the output is:
2020-12-11T13:23:58.677.000Z
How can I keep the timezone? or even better, can I set my own timezone?
the desired output is:
2020-12-11T13:23:58.677-04:00

MongoDB's BSON date type always stores dates as UTC date/times, so you cannot store an offset directly in a BSON date field. You can choose to store your offset in a separate field with something like:
from pymongo import MongoClient
from dateutil import parser
db = MongoClient()['mydatabase']
dt = parser.parse('2020-12-11T13:23:58.677-04:00')
db.questionsActual.insert_one({'date': dt, 'offsetSeconds': dt.tzinfo.utcoffset(dt).total_seconds()})
print(db.questionsActual.find_one({}, {'_id': 0}))
gives:
{'date': datetime.datetime(2020, 12, 11, 17, 23, 58, 677000), 'offsetSeconds': -14400.0}

Related

Find document by date - MongoDB - Python [duplicate]

This question already has answers here:
MongoDB / Pymongo Query with Datetime
(2 answers)
Closed 7 years ago.
I have documents in a MongoDB collection that have a filed 'date'. In the Mongo Shell they appear as ISO Date.
For example:
"date" : ISODate("2015-12-21T09:00:05.396Z")
I would like to find documents within a certain range date.
The documents were inserted with PyMongo if it makes any difference.
How can I do this?
Thanks!
Operate regular Python datetime objects (documentation sample):
from datetime import datetime
start = datetime(2015, 12, 20, 7, 51, 04)
end = datetime(2015, 12, 21, 7, 52, 04)
col.find_one({'date': {'$lt': end, '$gt': start}})

Mongodb Date() returning the wrong value

from the mongodb shell, I'm having an issue with a date query. This is a test database and the problem is better explained by example:
Example field in a collection
"createdOn" : ISODate("2015-11-23T00:49:01.800Z")
When I enter a date of this month for testing at the shell such as:
new Date(2015, 11, 23)
ISODate("2015-12-23T05:00:00Z")
You can see it's a month a head, meaning It's messing my queries. Where I have to drop back a month in order to get what I need for this month:
db.collection.find({'createdOn': {'$lte': new Date(2015, 10, 23)}}).count()
306
db.collection.find({'createdOn': {'$gte': new Date(2015, 10, 23)}}).count()
10
All entries above were created in Nov, but when using the correct month:
db.collection.find({'createdOn': {'$gte': new Date(2015, 11, 23)}}).count()
0
How does this even happen?
You should use Date like this: new Date("2015-11-23"). See Mongo Reference
What you are doing is almost right but you have missed on a point that:
Javascript counts month from 0 to 11 instead of 1 to 12
January is 0. December is 11. So to see for entries created in november you have to apply query like:
db.collection.find({'createdOn': {'$gte': new Date(2015, 10, 23)}})

Find objects between two dates along with specific time MongoDB

I have been trying to filter all the objects which are created within a specific date range as well a specific time range.
For example: Consider the following scenario
if following are my filter's start date, end date, start time and end time.
startDate: 23/01/2015 endDate: 25/01/2015
startTime: 10:00:00 endTime: 16:00:00
So I need to filter all the objects which are created between the startDate(23/01/2015) and endDate(25/01/2015). Also the creation time should be between startTime(10:00:00) and endTime(16:00:00).
So an object which is created on 24/01/2015 but at 09:00:00 will not be filtered according to my use case.
Is there any mongo query to achieve the same where we can pass date and time separately. If not kindly suggest some workaround.
for (var d = new Date(2015, 0, 23, 10, 00, 00); d <= new Date(2015, 0,25,16,00,00); d.setDate(d.getDate() + 1)) {
var d1 = d.setHours(d.getHours()+6);
db.coll.find({createdDate:{$gte:d, $lte:d1}})
}

mongodb query for date fields

I save a mongodb field 'date' as datetime object
and use following queries
1.db.test_collection.find({'date': {'$gte': start_date_time}})
2. db.test_collection.find({"date": {"$gte": start_date_time, "$lte": end_date_time}
where start_date_time is (say)2014-06-03 00:00:00 and end_date_time 2014-06-03 23:59:59
i insert some values to mongodb, But I don't give any results.
please help me to solve the issue.
You should use the datetime type.
import datetime
db.test_collection.find({'date': {'$gte': datetime.datetime(2014, 6, 3, 16, 46) }})
You can see more in the documentation (http://api.mongodb.org/python/current/tutorial.html)
Hope it works fine for you!

mongodb remove all dates less than specified

I have the following data.
{
deviceID: 186,
date: "2014-3-15"
}
{
deviceID: 186,
date: "2014-3-14"
}
{
deviceID: 186,
date: "2014-3-13"
}
And some lower dates, like 2014-3-9 , 8 ,7 ,6 etc.
When doing a db.coll.remove({date:{$lte:"2014-3-5"}})
Mongo removes the 15,14,13 aswell, but keeps single digit day dates. Is this maybe due to the date is a string?
I dont know how else to format the date so I can remove all dates below a certain date.
It is supposed to be a cleaning process, removing all documents with a date lower than specified.
Its because the date field you are querying on is a string filed and not a Date(). In your mongo documents instead of a custom date string, insert javascript date objects into date field.
like
{ deviceID: 186,,"date": new Date(2012, 7, 14) }
and when you execute the remove do it like
db.coll.remove({date:{$lte:new Date(2012, 7, 14)}})
If you want to remove data from MongoDB from the date less than specified, you MUST make sure of the date.
Easiest way for you to check whether you are inputting the right format is to test it before you use it in your query.
For example if you want to get current date in ISODate in Mongo shell, just type new Date and you will get the current date in Mongo.
I've tried the following in the Mongo shell:
new Date(2017, 11, 1)
and it returns
ISODate("2017-11-30T16:00:00Z")
which is not what I wanted.
What I want is to delete data before 1 November 2017.
Here's what works for me:
new Date("2017-11-01")
and it returns:
ISODate("2017-11-01T00:00:00Z")
Which is what I wanted.
This is because you are storing your data in a wrong format. You have a string an string
'15' is smaller than string '5'. Convert your strings in the beginning to date (read here how to use dates in mongo).
And only than you can use it to properly compare your dates:
db.coll.remove({
date:{
$lte : new Date(2012, 7, 14)
}
})
The reason for this is is your dates are strings.
So in a lexical sense when comparing strings "2014-3-5" is greater than "2014-3-15", as what is being compared is that "1" is less than "5".
Fix your dates as real ISO Dates, or you will forever have this problem.
Batch convert like this, assuming "year" "month" "day" in format:
db.eval(function(){
db.collection.find().forEach(function(doc) {
var d = doc.date.split("-");
var date = new Date(
"" + d[0] + "-" +
( d[1] <= 9 ) ? "0" + d[1] : d[1] + "-" +
( d[2] <= 9 ) ? "0" + d[2] : d[2]
);
db.collection.update(
{ "_id": doc._id },
{ "$set": { "date": date }
);
});
})
That makes sure you get the right dates on conversion.