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

如何基于Django Clocking模型统计用户每日工时?

解决方案:统计用户每日工时并生成工时列表

核心思路

  1. 解析字符串格式的打卡时间(12小时制AM/PM)为时间对象
  2. 计算单次打卡的时长,按日期分组累加
  3. 格式化结果为指定的字符串列表格式

代码实现(Django视图/工具函数)

首先导入必要模块:

import datetime
from .models import Clocking

编写获取每日工时的函数:

def get_user_daily_work_hours(user_id):
    # 获取目标用户的所有打卡记录,按日期排序
    clockings = Clocking.objects.filter(user_id=user_id).order_by('date')
    
    daily_total = {}
    for record in clockings:
        # 跳过无效的时间记录
        if not record.timein or not record.timeout:
            continue
        
        try:
            # 解析12小时制时间字符串为时间对象
            time_in = datetime.datetime.strptime(record.timein, '%I:%M %p').time()
            time_out = datetime.datetime.strptime(record.timeout, '%I:%M %p').time()
        except ValueError:
            # 处理格式错误的时间,直接跳过该条记录
            continue
        
        # 计算单次打卡时长(转换为小时)
        time_diff = datetime.datetime.combine(datetime.date.today(), time_out) - datetime.datetime.combine(datetime.date.today(), time_in)
        single_hours = time_diff.total_seconds() / 3600
        
        # 按日期累加总工时
        date_key = str(record.date)
        if date_key not in daily_total:
            daily_total[date_key] = 0.0
        daily_total[date_key] += single_hours
    
    # 按日期排序后提取工时列表,保留1位小数
    sorted_dates = sorted(daily_total.keys())
    hours_list = [f"{daily_total[date]:.1f}" for date in sorted_dates]
    
    return hours_list

关键说明

  • 时间解析:使用%I:%M %p格式匹配12小时制的时间字符串(如10:42 AM)
  • 异常处理:跳过空值或格式错误的时间记录,避免程序崩溃
  • 分组累加:通过字典按日期存储当日总工时,确保同一日期的多次打卡时长被正确累加
  • 格式输出:最终列表中的工时保留1位小数,符合示例中的6.8格式

扩展优化(可选)

如果需要包含无打卡记录的日期(如中间某天未打卡显示0.0),可以先生成指定日期范围,再填充工时数据:

def get_user_daily_work_hours_with_range(user_id, start_date, end_date):
    # 生成日期范围内的所有日期
    date_range = [start_date + datetime.timedelta(days=i) for i in range((end_date - start_date).days + 1)]
    date_str_range = [str(date) for date in date_range]
    
    # 初始化每日工时为0
    daily_total = {date:0.0 for date in date_str_range}
    
    # 获取该日期范围内的打卡记录
    clockings = Clocking.objects.filter(user_id=user_id, date__range=(start_date, end_date)).order_by('date')
    
    for record in clockings:
        # 复用之前的时间解析和时长计算逻辑
        if not record.timein or not record.timeout:
            continue
        try:
            time_in = datetime.datetime.strptime(record.timein, '%I:%M %p').time()
            time_out = datetime.datetime.strptime(record.timeout, '%I:%M %p').time()
        except ValueError:
            continue
        time_diff = datetime.datetime.combine(datetime.date.today(), time_out) - datetime.datetime.combine(datetime.date.today(), time_in)
        single_hours = time_diff.total_seconds() / 3600
        
        daily_total[str(record.date)] += single_hours
    
    # 按日期顺序生成列表
    hours_list = [f"{daily_total[date]:.1f}" for date in date_str_range]
    return hours_list

内容的提问来源于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 09:17:01