You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Annotation:如何将时间差转换为整数或小数表示小时?

解决方案:将工时总和转为小时数(整数/小数)

在Django中,Sum(F('clockout') - F('clockin'))返回的是timedelta类型(格式为HH:mm:ss),要转成整数或小数形式的小时数,有两种可行方案:

方法1:数据库层面直接计算(推荐,性能更优)

利用Django的数据库函数,直接在查询阶段将工时总和转为小时数:

步骤1:导入所需函数

from django.db.models import F, Sum, IntegerField, Cast
from django.db.models.functions import ExtractTotalSeconds, Round
from django.db.models.functions import TruncDate

步骤2:修改查询代码

得到小数形式的小时数

day = Clocking.objects.filter(clockout__isnull=False, user=nid)
    .annotate(date=TruncDate('clockin'))
    .values('date')
    .annotate(total_seconds=Sum(ExtractTotalSeconds(F('clockout') - F('clockin'))))
    .annotate(total_hours=F('total_seconds') / 3600)
    .values('date', 'total_hours')

这里先计算所有工时的总秒数,再除以3600得到精确的小时数(如6.5)。

转成整数形式

如果需要整数结果,可选择两种方式:

  • 四舍五入:
.annotate(total_hours=Round(F('total_seconds') / 3600))
  • 截断小数部分(直接取整):
.annotate(total_hours=Cast(F('total_seconds') / 3600, IntegerField()))

方法2:Python层面处理Timedelta

如果不想修改数据库查询逻辑,可在获取查询结果后,在Python中转换:

# 执行原查询
day_queryset = Clocking.objects.filter(clockout__isnull=False, user=nid)
    .annotate(date=TruncDate('clockin'))
    .values('date').annotate(total=Sum(F('clockout') - F('clockin')))

# 遍历转换
processed_result = []
for item in day_queryset:
    timedelta_total = item['total']
    # 转成小数小时
    total_hours = timedelta_total.total_seconds() / 3600
    # 可选:转整数
    # total_hours = int(total_hours)  # 截断小数
    # total_hours = round(total_hours)  # 四舍五入
    processed_result.append({
        'date': item['date'],
        'total_hours': total_hours
    })

timedelta对象的total_seconds()方法可获取总秒数,除以3600即可得到小时数。


内容的提问来源于stack exchange,提问作者zheni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 12:52:24