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

时间:2009-05-27 21:03:18

标签: python django

在模型中,“输入”是日期时间字段。我想查询数据以找到中午(start_time)和下午5:00(end_time)之间的所有条目。

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 个答案:

答案 0 :(得分:5)

我不相信有内置的支持,但您可以传递extra where-clause个参数(警告:这里可能会引入与DB相关的行为)。

例如,在Postgres上,例如:

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

如果您使用可能不安全的输入来确定值1217,请注意您还可以指定额外的params选项以确保正确引用和转义,然后使用where语句中的标准sql %s占位符。

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

您可以使用db的机制来过滤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)

但我认为这两种解决方案都很丑陋。

史蒂夫,你必须决定,对你来说不那么难看:

  • 在for循环中处理大量数据,
  • 或使用.extra(..)并绕过orm-system

答案 3 :(得分:0)

您是否为start_timeend_time提供了datetime objects

快速试用:

class Entry(models.Model):
    entered = models.DateTimeField()

>>> from datetime import datetime
>>> Entry(entered = datetime.now()).save()
>>> Entry.objects.filter(entered__lte = datetime.now())
[<Entry: Entry object>]
>>> Entry.objects.filter(entered__gte = datetime.now())
[]
>>> Entry.objects.filter(entered__gte = datetime.now(), entered__lte=datetime(2009,11,1,0,0))
[<Entry: Entry object>]

答案 4 :(得分:0)

我建议过滤x<=arg并排除x>=arg2

答案 5 :(得分:0)

我刚刚找到了一个类似用例的解决方案 - 也许有人觉得这很有用:

就我而言,我有可用性和约束模型,如此(简化):

class Availability(...):
    start = models.DateTimeField()
    end = models.DateTimeField()

class Constraint(...):
    from = models.TimeField()
    to = models.TimeField()

我想找到不违反任何限制的可用性。

对于Postgres,这对我有用:

Availability.objects.extra(
    where=['NOT (start::time, "end"::time) OVERLAPS (\'{0}\'::time, \'{1}\'::time)'.format(
        from.strftime("%H:%M"), to.strftime("%H:%M")
    )]
)

请注意您如何使用DateTimeTime投放到timestamp(或者更确切地说time without timezone ::time OVERLAPS in Postgres),然后使用Availability.objects.extra( where=['start::time BETWEEN \'{0}\'::time AND \'{1}\'::time AND "end"::time BETWEEN \'{0}\'::time AND \'{1}\'::time'.format( from.strftime("%H:%M"), to.strftime("%H:%M") )] ) 比较时间范围。

关于原始问题,你也可以这样做:

.test {
  border: solid 1px blue;
  width: 600px;
  height: 50px;
  background-repeat: no-repeat;
  background-image: radial-gradient(circle at 50% -563px, red 600px, transparent 600px), 
                    radial-gradient(circle at 50% 603px, transparent 600px, red 600px);
  background-size: 50% 40px;
  background-position: left bottom, right bottom;
}

答案 6 :(得分:-2)

您可以使用范围在两者之间进行过滤。我发现这是过滤的最佳方式,因为SQL的过滤效果比Django好。

fromRange=datetime.datetime.strptime(request.GET.get('from'),'%Y-%m-%dT%H:%M:%S.%fZ')
toRange=datetime.datetime.strptime(request.GET.get('to'),'%Y-%m-%dT%H:%M:%S.%fZ')

entry = Entry.objects.filter(entryTime__range=(fromRange,toRange))