在 Django QuerySet 中,可以在两个日期之间获取月份



我正在尝试创建一个完整的查询集,现在我所需要的只是从我的模型中获取两个DateTime字段之间的月份,可以在单个查询集中执行此操作。我不是在谈论过滤器,因为在模型中例如我有两个datetimeField(),现在我想做的是,在这个日期之间得到几个月。

如果你的数据库支持DurationField你可以使用 ExtractMonth:

from django.db import models
from django.db.models.functions import ExtractMonth
queryset = MyModel.objects.annotate(
    diff=models.ExpressionWrapper(
        models.F('date1') - models.F('date2'), output_field=models.DurationField())
    ).annotate(months=ExtractMonth('diff'))

给定的答案对我在 postgres 上不起作用,因为diff字段(持续时间字段(仅支持Extract天功能。 ExtractMonth返回"0"。

这是我找到的解决方案:

queryset = MyModel.objects.annotate(
    months=(ExtractYear("date2") - ExtractYear("date1")) * 12 + (ExtractMonth("date2") - ExtractMonth("date1"))
)

请注意,它只考虑每个月第一天之间的差异,而不是按天数给出的最终小数部分。在此解决方案中,2020-08-12 被视为与 2020-08-01 相同。

Django v4.0.4 PostgreSQL v13.4

date2_date1_months_elapsed 返回两个日期之间经过了多少个月(以整数形式(。

created_on_months_elapsed返回从今天到创建日期之间经过了多少个月(整数(。

from django.db.models import F, IntegerField
from django.db.models.functions import Cast, ExtractDay, TruncDate
from django.utils import timezone

class MyModel(models.Model):
    date1 = models.DateTimeField()
    date2 = models.DateTimeField()
    created_on = models.DateTimeField(default=timezone.now)
    ...

queryset = MyModel.objects.annotate(
    date2_date1_days_diff=Cast(
        ExtractDay(
            TruncDate(F("date2")) - TruncDate(F("date1"))
        ),
        IntegerField(),
    ),
    date2_date1_months_elapsed=Cast(
        F("date2_date1_days_diff") / (365 / 12), IntegerField()
    ),
    created_on_days_diff=Cast(
        ExtractDay(
            TruncDate(timezone.now()) - TruncDate(F("created_on"))
        ),
        IntegerField(),
    ),
    created_on_months_elapsed=Cast(
        F("created_on_days_diff") / (365 / 12), IntegerField()
    )
)

最新更新