如何基于Django Clocking模型统计用户每日工时?
解决方案:统计用户每日工时并生成工时列表
核心思路
- 解析字符串格式的打卡时间(12小时制AM/PM)为时间对象
- 计算单次打卡的时长,按日期分组累加
- 格式化结果为指定的字符串列表格式
代码实现(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
相关产品推荐
相关产品推荐

