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

MongoDB计算time-in与time-out时间差求和并转小时格式方案

MongoDB计算考勤打卡总时长实现方案

实现思路

  • 展开嵌套的record打卡数组,将每一条打卡记录作为独立文档处理
  • 对所有打卡记录按时间升序排序,保证打卡顺序正确
  • 按打卡日期分组,分别收集当天的所有上班(time-in)和下班(time-out)时间戳
  • 按索引位置配对同组的上班和下班时间,计算单组打卡的时长差值
  • 累加所有差值得到总毫秒数,最后转换为小时格式

具体聚合查询代码

db.你的集合名.aggregate([
  // 第一步:展开record数组
  { $unwind: "$record" },
  // 第二步:提取打卡日期、时间戳、状态,方便后续处理
  {
    $project: {
      date: {
        $dateToString: {
          format: "%Y-%m-%d",
          date: "$record.dateTime.$date"
        }
      },
      timestamp: { $toLong: "$record.dateTime.$date" },
      status: "$record.status"
    }
  },
  // 第三步:按日期分组,分别收集上下班时间列表
  {
    $group: {
      _id: "$date",
      timeIns: {
        $push: {
          $cond: [{ $eq: ["$status", "time-in"] }, "$timestamp", "$$REMOVE"]
        }
      },
      timeOuts: {
        $push: {
          $cond: [{ $eq: ["$status", "time-out"] }, "$timestamp", "$$REMOVE"]
        }
      }
    }
  },
  // 第四步:配对上下班时间,计算单日总时长(毫秒)
  {
    $project: {
      dayTotalMs: {
        $sum: {
          $map: {
            input: { $range: [0, { $size: "$timeIns" }] },
            as: "idx",
            in: {
              $subtract: [
                { $arrayElemAt: ["$timeOuts", "$$idx"] },
                { $arrayElemAt: ["$timeIns", "$$idx"] }
              ]
            }
          }
        }
      }
    }
  },
  // 第五步:累加所有日期的时长,转换为小时
  {
    $group: {
      _id: null,
      totalMs: { $sum: "$dayTotalMs" }
    }
  },
  {
    $project: {
      _id: 0,
      // 毫秒转小时:除以 1000*60*60 = 3600000
      totalWorkHours: { $divide: ["$totalMs", 3600000] }
    }
  }
])

补充说明

  • 如果业务允许同一天有多段打卡记录(比如上午、下午分别打卡),上述代码会自动按顺序配对计算
  • 如果需要保留两位小数的小时格式,可以在最后一步的$divide外包裹$round操作:totalWorkHours: { $round: [ { $divide: ["$totalMs", 3600000] }, 2 ] }
  • 请把代码里的你的集合名替换为你实际的集合名称

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:15:05