Python/Sqlalchemy/Sqlite - 如何在条件下添加日期时间字段和整数秒(timedelta)?

发布于 2025-01-11 06:45:15 字数 883 浏览 0 评论 0原文

我有一个 sqlalchemy/sqlite 表:

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 执行相同操作

I have a sqlalchemy/sqlite table:

class MyTable(Base):
    __tablename__ = 'mytable'
    ...
    field_dt = Column(DateTime)
    field_int = Column(Integer, default=0)

Now I would like to construct the where condition in which I want to check whether field_dt + field_int (seconds) <= utc_now.
Something like: select(MyTable).where(?).

With no sqlalchemy/sqlite I would construct condition like this:

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')

Output:

  utc_now = 2022-03-02T01:00:10
 field_dt = 2022-03-01T01:00:05
field_int = 60
it is less than utc_now

How to do the same with sqlalchemy/sqlite

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

物价感观 2025-01-18 06:45:15

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');

SQLAlchemy 等价的是:

q = sa.select(MyTable).where(
    sa.func.datetime(
        MyTable.field_dt,
        '+' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
    )
    < dt.datetime.utcnow()
)

如果 field_dt 被索引,请考虑将修饰符移动到不等式的 RHS:

q = sa.select(MyTable).where(
    MyTable.field_dt
    < sa.func.datetime(
        dt.datetime.utcnow(),
        '-' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
    )
)

可能值得考虑将日期时间存储为 Unix 时间戳以简化查询。

SQLite 日期函数文档位于此处

SQLite 3.38.0 implements a unixepoch function that can convert a datetime to a Unix timestamp, so in theory we could do

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)
)

however 3.38.0 was released on 2022-02-22 so at the time of writing it may not be widely distributed.

If unixepoch is not available we can use SQLite's datetime function to construct a new datetime. The SQL would look something like this:

select datetime(field_dt, '+' || cast(field_int as text) || ' seconds') as dt
from mytable
where dt < datetime('now');

the SQLAlchemy equivalent is:

q = sa.select(MyTable).where(
    sa.func.datetime(
        MyTable.field_dt,
        '+' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
    )
    < dt.datetime.utcnow()
)

If field_dt is indexed, consider moving the modifier to the RHS of the inequality:

q = sa.select(MyTable).where(
    MyTable.field_dt
    < sa.func.datetime(
        dt.datetime.utcnow(),
        '-' + sa.cast(MyTable.field_int, sa.String) + ' seconds',
    )
)

It may be worth considering storing the datetime as a Unix timestamp to simplify the query.

The SQLite date functions documentation is here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文