How to compare dates in sqlalchemy?

Question:

I have the following simple setup, where fromDate and toDate are strings on the format “YYYY-MM-DD”:

class SomeType(Base):
    date = Column(DateTime)

def findAll(fromDate, toDate):
    return session.query(SomeType).filter(SomeType.date >= fromDate, SomeType.date <= toDate).all()

The problem is that it doesn’t find what I want it to find unless I modify the input dates like this:

def findAll(fromDate, toDate):
    fromDate = fromDate + " 00:00"
    toDate = toDate + " 24:00"
    return session.query(SomeType).filter(SomeType.date >= fromDate, SomeType.date <= toDate).all()

But that doesn’t look good. Any ideas on how I can do this the right way?

Asked By: Markus Johansson

||

Answers:

How about using datetime.datetime objects instead of strings for fromDate, toDate?

from datetime import datetime, timedelta

def findAll(fromDate, toDate):
    fromDate = datetime.strptime(fromDate, '%Y-%m-%d')
    toDate = datetime.strptime(toDate, '%Y-%m-%d') + timedelta(days=1)
    return session.query(SomeType).filter(
        SomeType.date >= fromDate,
        SomeType.date < toDate).all()
Answered By: falsetru

The problem is that your SomeType.date column is not simple date, but is datetime column, so it contains also a time component.

This type mismatch is the cause of your problem. If this is the case then following should work:

session.query(SomeType).filter(func.date(SomeType.date) >= fromDate, func.date(SomeType.date) <= toDate).all()

where we basically cast datetime to date using DATE(...) function of MySql.

However, I would probably also prefer working with date(time) data types instead of strings. You are just lucky that most databases implicitly allow parsing of ISO-compliant string representations of DATEs.

Answered By: van

I know this is old, but while trying to find my answer, I found datetime.combine

you can do

select(SomeTable)
.filter( SomeTable.datetime_issued >= datetime.combine(start_date, time.min),
         SomeTable.datetime_issued <= datetime.combine(end_date, time.max))

datetime.combine will combine date and time into datetime

https://docs.python.org/3/library/datetime.html#datetime.datetime.combine

When combining, you should use time.min, time.max which will give you min and max time

print(combine(date.today(), time.min), combine(date.today(), time.max))

This will print

2022-10-14 00:00:00, 2022-10-14 23:59:59.999999

https://docs.python.org/3/library/datetime.html#datetime.time.max

Answered By: Turtles
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.