MongoDb + Python datetime without time

I want to insert to BD just year+month+day(2022-03-20) without time.
I try to do it
collection.insert_one({… “date”: datetime.date.today()}) (sqlite3 all ok)
But got an error: cannot encode object datetime.date
OR:
datetime.datetime.now()
now.strftime("%Y-%m-%d") - MongoDB thinks what it’s a string :frowning:
When I try: collection.insert_one({… “date”:datetime.datetime.now()}) - it’s working, but format is bad.
2022-03-20T00:08:17.080+00:00

How to insert to Mongo just (year-month-day)?

Or if I have date in format “2022-03-20T00:08:17.080+00:00”, How can i find all todays?

Hi Alex, welcome to community. :confetti_ball:

Mongodb stores datetime value as UTC datetime format. We don’t have an option storing this data without time and time zone information.

Maybe you can try to storing formatted data as string, generally people doing this. When comparing values you have to need convert data to string for comparation value.

For example we have a collection that name is date_exp and it contains following data;

{
       "date":"2022-10-12"
}
{
       "date":"2022-10-30"
}
{
       "date":"2022-11-15"
}
{
       "date":"2022-12-15"
}

with this string data we can query the collection like following;

//query 1: specified date query
db.getCollection('date_exp').find({
    "date":"2022-10-30"
    })

//query 2: date range query
db.getCollection('date_exp').find({
    "date":{"$gt": "2022-10-28" , "$lt":"2022-11-30"}
    })

Query results;

// results 1 belongs to query 1
/* 1 */
{
    "_id" : ObjectId("623c5d63d0a4d1f348bd336d"),
    "date" : "2022-10-30"
}

//results 2 belongs to query 2
/* 1 */
{
    "_id" : ObjectId("623c5d63d0a4d1f348bd336d"),
    "date" : "2022-10-30"
}

/* 2 */
{
    "_id" : ObjectId("623c5d63d0a4d1f348bd3370"),
    "date" : "2022-11-15"
}

As we see, querying returns result as expected. It’s good to keep in mind that we have to store data format ordered as year, month, day. Otherwise things can be broken.


If you want to store data as UTC datetime format you can chose to using similar approach.

For example if our field had been datetime;
Sample data;

{
    "date":ISODate("2022-03-23T15:33:15.551Z")
}
{
    "date":ISODate("2022-03-23T15:19:15.551Z")
}
{
    "date":ISODate("2022-03-23T20:33:15.551Z")
}
{
    "date":ISODate("2022-03-21T20:33:15.551Z")
}
{
    "date":ISODate("2022-03-25T20:33:15.551Z")
}

new query; (queried specified day between 23 march 2022 00:00 and 24 march 2022 00:00)

db.getCollection('date_test').find({
       "date":{"$gte":new Date("2022-03-23"),"$lt":new Date("2022-03-24")}
    })

and results;

/* 1 */
{
    "_id" : ObjectId("623c5fd4d0a4d1f348bd33ec"),
    "date" : ISODate("2022-03-23T15:33:15.551Z")
}

/* 2 */
{
    "_id" : ObjectId("623c5fd4d0a4d1f348bd33ef"),
    "date" : ISODate("2022-03-23T15:19:15.551Z")
}

/* 3 */
{
    "_id" : ObjectId("623c5fd4d0a4d1f348bd33f2"),
    "date" : ISODate("2022-03-23T20:33:15.551Z")
}

I hope these are useful.

Favor the UTC approach presented by @Hazel_Cakli, rather than the string version.

  1. dates takes less space

You can check by your self with:

db.date_as_date.insertOne( { _id:0 , date : new Date() })
{ acknowledged: true, insertedId: 0 }
db.date_as_string.insertOne( { _id:0 , date : "2022-03-24" })
{ acknowledged: true, insertedId: 0 }

and then check the average size of a document. This size advantage is also present in your indexes.

  1. A much richer API to manipulate as date

You can add days, months, weeks very easily if you use the date data type compared to string or anything else.

  1. Faster, a date data type comparison is most likely a single number comparison, while a string date implies character per character comparison. And when compare days it is the last two characters that differs.

If you are worry about how the date is shown to the end users, you should not because you are supposed to format the date using the user’s LOCALE anyway.

1 Like