简体   繁体   English

Django 按时间过滤日期时间字段,不考虑日期

[英]Django filter datetime field by time, irrespective of date

I have a datetime field in Django, and I want to filter this based on time.我在 Django 中有一个日期时间字段,我想根据时间过滤它。 I don't care about the particular date, but I want to find all transactions before 7:30, for example.我不关心特定日期,但我想查找 7:30 之前的所有交易,例如。

I know I can filter by hour and minute such as:我知道我可以按小时和分钟过滤,例如:

Q(datetime__hour=7) & \
Q(datetime__minute=30)

However, this would find all transactions AT 7:30.但是,这会在 7:30 找到所有交易。 You are also unable to apply gte or lte.您也无法申请 gte 或 lte。 ie IE

(Q(datetime__hour__lte=7) & \
Q(datetime__minute__lte=30)) | \
Q(datetime__hour__lt=7)

The only thing that appears to be a potential solution is to have many queries, such as:唯一似乎是潜在解决方案的是有许多查询,例如:

(Q(datetime__hour=7) & \
(Q(datetime__minute=30) | \
 Q(datetime__minute=29) | \
 Q(datetime__minute=28) | \
 ....
 Q(datetime__minute=2) | \
 Q(datetime__minute=1) | \
 Q(datetime__minute=0))) | \
Q(datetime__hour=6) | \
Q(datetime__hour=5) | \
Q(datetime__hour=4) | \
Q(datetime__hour=3) | \
Q(datetime__hour=2) | \
Q(datetime__hour=1) | \
Q(datetime__hour=0)

But this seems ridiculous.但这似乎很荒谬。

Anyone have any ideas?有人有主意吗?

Just split the datetime field into a date and a time field.只需将日期时间字段拆分为日期和时间字段即可。 Than you can filter on time only:比你只能按时过滤:

from datetime import combine

class MyModel(models.Model):
    start_date = models.DateField()
    start_time = models.TimeField()

    class Meta:
        ordering = ['start_date', 'start_time']

    def start_datetime(self):
        return combine(self.date, self.time)

I added the Meta.ordering and start_datetime model method to show that this model can present data in the same way a model with a DateTimeField can.我添加了 Meta.ordering 和 start_datetime model 方法来表明这个 model 可以像带有 DateTimeField 的 model 一样呈现数据。

Now you can filter on time:现在您可以按时过滤:

objects = MyModel.objects.filter(start_time__lt=time(7, 30))

Update更新

If you have a established project and many queries depend on having a normal DateTime field.如果您有一个已建立的项目并且许多查询都依赖于具有正常的 DateTime 字段。 Splitting the datetime into a date and time fields come a cost: Rewriting queries threw out your project.将日期时间拆分为日期和时间字段是有代价的:重写查询会使您的项目失败。 There is an alternative: Only add a time field and leave the datetime field untouched.有一个替代方案:只添加一个时间字段并保持日期时间字段不变。 A save method can add the time based on datetime.保存方法可以根据日期时间添加时间。 The down side is that you have duplicated data in your db.不利的一面是您的数据库中有重复的数据。 The good thing it solves your problem with minimal effort.好处是它可以以最小的努力解决您的问题。

class MyModel(models.Model):
    start_datetime = models.DateTimeField()
    start_time = models.TimeField(blank=True)

    def save(self)
        self.start_time = self.start_datetime.time

All existing queries will be the same as before and filter on time only:所有现有查询都将与以前相同,并且仅按时间过滤:

objects = MyModel.objects.filter(start_time__lt=time(7, 30))

In Django 1.7+ you could use a transform to extract minute and hour from the timestamp.在 Django 1.7+ 中,您可以使用转换从时间戳中提取分钟和小时。 See https://docs.djangoproject.com/en/1.7/howto/custom-lookups/#a-simple-transformer-example for details.有关详细信息,请参阅https://docs.djangoproject.com/en/1.7/howto/custom-lookups/#a-simple-transformer-example

Not sure when the filter by time was introduced, but in recent versions of Django (4.0+) this is done by the following query syntax:不确定何时引入按时间筛选,但在 Django (4.0+) 的最新版本中,这是通过以下查询语法完成的:

YourModel.objects.all().filter(datetime__hour__lte=7, datetime__minute__lte=30)

Where YourModel is the model you are filtering, and datetime is the field from that model.其中YourModel是您要过滤的 model, datetime是来自该 model 的字段。

Ideas:想法:

  • use raw sql使用原始 sql
  • (mem)cache your results (eq::pseudocode:: md5(sql_string) = sql_result). (mem) 缓存你的结果 (eq::pseudocode:: md5(sql_string) = sql_result)。
  • create a middle table with 5 indexed integer columns (year, month, day, hour, minute).创建一个包含 5 个索引 integer 列(年、月、日、小时、分钟)的中间表。 Before your main sql extraction check this table for the needed data (the query should be really fast).在您主要的 sql 提取之前检查此表以获取所需的数据(查询应该非常快)。 If nothing exists, make your "magic" transaction (preferably not using Django's ORM).如果什么都不存在,请进行“神奇”交易(最好不要使用 Django 的 ORM)。 The result use it for your purpose, but also duplicate it into your secondary table.结果将其用于您的目的,但也将其复制到您的辅助表中。
  • when you get tired of doing unnecessary operations, kill some sleep hours and optimize your sql structure, based on the projects needs: what data is needed, amount of db writes vs amount of db reads, inner/outer joins and so on...当你厌倦了做不必要的操作时,减少一些睡眠时间并根据项目需求优化你的 sql 结构:需要什么数据,数据库写入量与数据库读取量,内部/外部连接等等......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM