Disclaimer 1: First of all, consider whether it is generally โcheaperโ to use postgresql instead of sqlite everywhere. I assume that you have development / production differences that should be avoided. Installing postgresql on any modern OS is pretty trivial.
Assuming this is not an option / desired, continue.
Failure 2: A solution with a custom SQL construct (as per @Josh's answer) is indeed the only reasonable way to achieve this. Unfortunately, the proposed solution does not actually work for sqlite and cannot be fixed with just a few lines, therefore, a separate answer.
Solution: Assuming you have the following model:
class Appointment(Base): __tablename__ = 'appointment' id = Column(Integer, primary_key=True) name = Column(String(255)) datetime = Column(DateTime)
sqlite really difficult to use date operations, especially adding / subtracting intervals from dates. Therefore, let's approach and create custom functions in a slightly different way to get the interval between two dates in minutes:
class diff_minutes(expression.FunctionElement): type = Integer() name = 'diff_minutes' @compiles(diff_minutes, 'sqlite') def sqlite_diff_minutes(element, compiler, **kw): dt1, dt2 = list(element.clauses) return compiler.process( (func.strftime('%s', dt1) - func.strftime('%s', dt2)) / 60 ) @compiles(diff_minutes, 'postgresql') def postgres_diff_minutes(element, compiler, **kw): dt1, dt2 = list(element.clauses) return compiler.process(func.extract('epoch', dt1 - dt2) / 60)
You can already implement your verification using the following query (I do not add limit(1).one_or_none to my examples, which you can obviously do when you need it):
q = ( session .query(Appointment) .filter(Appointment.datetime <= func.now()) .filter(diff_minutes(func.now(), Appointment.datetime) <= Appointment.duration) )
But now you are not limited by the current time ( func.now() ), and you can check (and unit test) your data at any time:
Basically the problem is solved here , and the solution should work for both of your database engines.
BONUS:
You can hide the implementation of checking whether the event is current using Hybrid methods .
Let's add the following to the Appointment class:
@hybrid_method def is_current(self, at_time=None): if at_time is None: at_time = datetime.datetime.now() return self.datetime <= at_time <= self.datetime + datetime.timedelta(minutes=self.duration) @is_current.expression def is_current(cls, at_time=None): if at_time is None: at_time = datetime.datetime.now() stime = cls.datetime diffm = diff_minutes(at_time, cls.datetime) return and_(diffm >= 0, cls.duration >= diffm).label('is_current')
The first allows you to run a check in memory (on python, not on the SQL side):
print(my_appointment.is_current())
The second method allows you to build a query, as shown below:
q = session.query(Appointment).filter(Appointment.is_current(at_time))
If if at_time not specified, the current time will be used. You can, of course, change the request as you wish:
current_appointment = session.query(Appointment).filter(Appointment.is_current()).limit(1).one_or_none()