Python/Sqlalchemy/Sqlite - 如何在where条件下添加日期时间字段和整数秒(timedelta)?
Python/Sqlalchemy/Sqlite - How to add datetime field and integer seconds (timedelta) in where condition?
我有一个 sqlalchemy/sqlite table:
class MyTable(Base):
__tablename__ = 'mytable'
...
field_dt = Column(DateTime)
field_int = Column(Integer, default=0)
现在我想构建 where 条件,我想在其中检查 field_dt + field_int(秒)<= utc_now。
类似于:select(MyTable).where(?)
.
没有 sqlalchemy/sqlite 我会构造这样的条件:
import datetime as dt
utc_now = dt.datetime(2022,3,2,1,0,10)
field_dt = dt.datetime(2022,3,1,1,0,5)
field_int = 60
print(f" utc_now = {utc_now.isoformat()}")
print(f" field_dt = {field_dt.isoformat()}")
print(f"field_int = {field_int}")
if field_dt + dt.timedelta(seconds=field_int) < utc_now:
print('it is less than utc_now')
输出:
utc_now = 2022-03-02T01:00:10
field_dt = 2022-03-01T01:00:05
field_int = 60
it is less than utc_now
如何用 sqlalchemy/sqlite
做同样的事情
SQLite 3.38.0 实现了一个 unixepoch
函数,可以将日期时间转换为 Unix 时间戳,所以理论上我们可以做
import sqlalchemy as sa
# Untested
q = sa.select(MyTable).where(
(sa.func.unixepoch(MyTable.field_dt) + MyTable.field_int)
< sa.func.unixepoch(dt.datetime.utcnow)
)
但是 3.38.0 于 2022 年 2 月 22 日发布,因此在撰写本文时它可能尚未广泛分发。
如果 unixepoch
不可用,我们可以使用 SQLite 的 datetime
函数来构造一个新的 datetime
。 SQL 看起来像这样:
select datetime(field_dt, '+' || cast(field_int as text) || ' seconds') as dt
from mytable
where dt < datetime('now');
SQL炼金术等价物是:
q = sa.select(MyTable).where(
sa.func.datetime(
MyTable.field_dt,
'+' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
)
< dt.datetime.utcnow()
)
如果 field_dt
被索引,考虑将修饰符移动到不等式的右侧:
q = sa.select(MyTable).where(
MyTable.field_dt
< sa.func.datetime(
dt.datetime.utcnow(),
'-' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
)
)
可能值得考虑将日期时间存储为 Unix 时间戳以简化查询。
SQLite 日期函数文档是 here。
我有一个 sqlalchemy/sqlite table:
class MyTable(Base):
__tablename__ = 'mytable'
...
field_dt = Column(DateTime)
field_int = Column(Integer, default=0)
现在我想构建 where 条件,我想在其中检查 field_dt + field_int(秒)<= utc_now。
类似于:select(MyTable).where(?)
.
没有 sqlalchemy/sqlite 我会构造这样的条件:
import datetime as dt
utc_now = dt.datetime(2022,3,2,1,0,10)
field_dt = dt.datetime(2022,3,1,1,0,5)
field_int = 60
print(f" utc_now = {utc_now.isoformat()}")
print(f" field_dt = {field_dt.isoformat()}")
print(f"field_int = {field_int}")
if field_dt + dt.timedelta(seconds=field_int) < utc_now:
print('it is less than utc_now')
输出:
utc_now = 2022-03-02T01:00:10
field_dt = 2022-03-01T01:00:05
field_int = 60
it is less than utc_now
如何用 sqlalchemy/sqlite
做同样的事情SQLite 3.38.0 实现了一个 unixepoch
函数,可以将日期时间转换为 Unix 时间戳,所以理论上我们可以做
import sqlalchemy as sa
# Untested
q = sa.select(MyTable).where(
(sa.func.unixepoch(MyTable.field_dt) + MyTable.field_int)
< sa.func.unixepoch(dt.datetime.utcnow)
)
但是 3.38.0 于 2022 年 2 月 22 日发布,因此在撰写本文时它可能尚未广泛分发。
如果 unixepoch
不可用,我们可以使用 SQLite 的 datetime
函数来构造一个新的 datetime
。 SQL 看起来像这样:
select datetime(field_dt, '+' || cast(field_int as text) || ' seconds') as dt
from mytable
where dt < datetime('now');
SQL炼金术等价物是:
q = sa.select(MyTable).where(
sa.func.datetime(
MyTable.field_dt,
'+' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
)
< dt.datetime.utcnow()
)
如果 field_dt
被索引,考虑将修饰符移动到不等式的右侧:
q = sa.select(MyTable).where(
MyTable.field_dt
< sa.func.datetime(
dt.datetime.utcnow(),
'-' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
)
)
可能值得考虑将日期时间存储为 Unix 时间戳以简化查询。
SQLite 日期函数文档是 here。