如何以天为单位注释日期时间的差异

Oli*_*Oli 2 django datetime django-annotate django-database-functions

我有一个Bookingstartenddatetime字段的模型.我想知道预订的天数.我可以在Python中执行此操作,但我需要此值以进行进一步注释.

这是我尝试过的:

In [1]: Booking.objects.annotate(days=F('end')-F('start'))[0].days
Out[1]: datetime.timedelta(16, 50400)
Run Code Online (Sandbox Code Playgroud)

这里有一些问题:

  • 我想要一个整数(或我可以在计算中使用的其他数字类型)作为输出,而不是timedelta.设置output_field在这里没有任何意义.
  • 我的总和是基于日期时间.像这样的减法,没有删除时间可能会导致整个天数关闭.

在Python中,我会这样做(end.date() - start.date()).days + 1.我怎样才能在数据库中做到这一点,最好是通过ORM(例如数据库函数),但是RawSQL这样就足以让它出门了?

Oli*_*Oli 6

我编写了几个数据库函数来转换和截断日期,以解决PostgreSQL下的两个问题。我使用的DATE_PARTDATE_TRUNC内部函数特定于DB?

from django.db.models import Func

class DiffDays(Func):
    function = 'DATE_PART'
    template = "%(function)s('day', %(expressions)s)"

class CastDate(Func):
    function = 'date_trunc'
    template = "%(function)s('day', %(expressions)s)"
Run Code Online (Sandbox Code Playgroud)

然后,我可以:

In [25]: Booking.objects.annotate(days=DiffDays(CastDate(F('end'))-CastDate(F('start'))) + 1)[0].days
Out[25]: 18.0
Run Code Online (Sandbox Code Playgroud)


小智 6

这个问题还有另一个简单的解决方案.您可以使用:

from django.db.models import F
from django.db.models.functions import ExtractDay
Run Code Online (Sandbox Code Playgroud)

然后:

Booking.objects.annotate(days=(ExtractDay(F('end')-F('start'))+1))[0].days
Run Code Online (Sandbox Code Playgroud)