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

Django如何基于DateTimeField字段计算每周、每月的总打卡时长

前置说明

默认你的inout字段业务规则是:1代表上班/入场打卡,0代表下班/离场打卡。如果你的实际规则不同,调整下方案里的对应过滤条件即可。


核心实现思路

打卡时长统计核心逻辑是先把同一用户的上下班打卡记录配对,计算出有效时长后再按周/月维度聚合,具体实现步骤如下:

步骤1:计算单日有效打卡时长

先按用户、自然天分组,取出每天最早的上班打卡和最晚的下班打卡,过滤掉只有上班/只有下班的无效单边记录,计算出单日有效时长:

import models
from django.db.models import F, ExpressionWrapper, DurationField, Sum, Min, Max
from django.db.models.functions import TruncDate, TruncWeek, TruncMonth

# 按用户+日期分组计算单日有效时长
daily_records = Clockin_Transaction.objects.values(
    "userid",
    "clockinusers",
    date=TruncDate("datetime")
).annotate(
    # 取当日最早的上班打卡时间
    first_clockin=Min("datetime", filter=models.Q(inout=1)),
    # 取当日最晚的下班打卡时间
    last_clockout=Max("datetime", filter=models.Q(inout=0))
).filter(
    # 过滤无效单边打卡记录
    first_clockin__isnull=False,
    last_clockout__isnull=False
).annotate(
    # 计算当日打卡时长
    daily_duration=ExpressionWrapper(
        F("last_clockout") - F("first_clockin"),
        output_field=DurationField()
    )
)

如果不需要按用户拆分统计,只看全平台总时长,把values里的userid、clockinusers字段删掉即可

步骤2:按周统计总打卡小时

基于上述单日时长结果,按周维度聚合求和:

weekly_stats = daily_records.values(
    "userid",
    "clockinusers",
    week=TruncWeek("date")
).annotate(
    total_duration=Sum("daily_duration")
).order_by("-week")

# 把时长转成小时单位
for item in weekly_stats:
    item["total_hours"] = item["total_duration"].total_seconds() / 3600

TruncWeek默认以周一为一周的起始,如果你的业务规则是周日为周起始,需要调整Django时区配置或者数据库周起始规则

步骤3:按月统计总打卡小时

和按周统计逻辑完全一致,把分组维度换成TruncMonth即可:

monthly_stats = daily_records.values(
    "userid",
    "clockinusers",
    month=TruncMonth("date")
).annotate(
    total_duration=Sum("daily_duration")
).order_by("-month")

# 转成小时单位
for item in monthly_stats:
    item["total_hours"] = item["total_duration"].total_seconds() / 3600

优化建议

  • 如果数据量超过10万条,建议单独建日/周/月统计结果表,用定时任务每天凌晨更新统计结果,避免每次查询都全量计算拖慢性能
  • 如果存在跨天加班场景(比如当日23点上班、次日凌晨5点下班),需要单独写逻辑处理跨天的打卡配对,不要直接按自然天截断记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:39:00