如何在日期时间字段中按时间过滤?

7 投票
7 回答
12585 浏览
提问于 2025-04-15 11:52

在这个模型中,'entered' 是一个日期时间字段。我想查询数据,找出所有在中午(开始时间)到下午5点(结束时间)之间的记录。

selected = Entry.objects.filter(entered__gte=start_time, entered__lte=end_time)

(正如我预料的那样)我遇到了一个错误:

"ValidationError: Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format."

所以我知道可以使用 __year,于是我尝试了一下。

selected = Entry.objects.filter(entered__time__gte=start_time, entered__time__lte=end_time)

结果我又遇到了一个错误:

"FieldError: Join on field 'start' not permitted. Did you misspell 'time' for the lookup type?"

7 个回答

3

以SQLite为例,一个相对简单和通用的解决方案是:

Entry.objects.extra(where=["time(entered) between '%s' and '%s'"],
                    params=[start_time.strftime("%H:%M"), end_time.strftime("%H:%M")])
7

我觉得这个功能没有内置支持,但你可以传递一些额外的条件参数(注意:这样做可能会引入与数据库相关的行为)。

比如,在Postgres数据库中,可以这样写:

Entry.objects.extra(where=['EXTRACT(hour from entered) >= 12 and '\
                    'EXTRACT(hour from entered) < 17'])

如果你使用一些可能不安全的输入来确定值 1217,请注意你还可以为额外的条件指定一个参数选项,这样可以确保正确的引号和转义,然后在你的条件语句中使用标准的sql %s 占位符。

1

你可以在Python中进行过滤,而不是使用数据库的机制:

for e in Entry.objects.all():
   if i.entered.hour>= 9 and i.entered.hour < 17 :# or break down to minutes/seconds
        list.append(e)

不过我觉得这两种解决方案都不太好看。

Steve,你得决定哪种方式对你来说更好一些:

  • 在一个循环中处理大量数据,
  • 还是使用 .extra(..) 来绕过ORM系统

撰写回答