使用moment.js计算工作总时长

878 阅读3分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

前言

最近接到了一个比较有意思的需求,计算一个员工在规定时间上下班的总时长。我觉得挺有意思的 特此分享给大家。

分析需求

  1. 用户可以自定义上班打卡的时间以及下班打卡的时间。 当上班打卡时间大于下班打卡时间时,用户为次日下班打卡
  2. 用户还可以自定义一个最早上班打卡的时间 以及一个最晚下班打卡的时间,最早上班打卡时间晚于上班打卡时间
  3. 最晚下班打卡时间不得早于下班打卡时间。
  4. 用户还可以定义多个时间段的休息时间。 比如早上9:00到下午6:00会有一个休息时间。产品这边没有强制要求休息时间的可选范围。
  5. 计算出用户的总工作时长(上班打卡时间~下班打卡时间区间的总时长 - 各休息时间区间之和)

该需求存在一些不完美的地方:

  1. 时间区间的选择是不存在跨日期的。前端的页面交互UI只涉及到了小时和分钟
  2. 休息时间可自定义时间范围(正常是应该在工作时间段内的。)
  3. 休息时间的重复区间

产品既然没有做这些需求 我们也就不强求 ~ ha ha

综上所述~我们可以定义出6个字段:上班打卡时间、下班打卡时间、最早上班打卡时间、最晚下班打卡时间、休息时间、工作总时长

定义数据对象

  // workTime.vue ..省略 template
  
<script>
 export default {
 name:'workTime',
 data(){
   return {
     form:{
      //上班打卡时间
      signIn:'',
      //下班打卡时间
      signOut:'',
      //最早上班打卡时间
      earliestSignIn:'',
      //最晚下班打卡时间
      earliestSignOut:'',
       },
    //restTime 休息区间  定义为 数组
    restTime: [{startTime:'0000',endTime:'0000'}]
    },
    computed:{
    totalWorkTime(){
     return this.calcTotalTime()
     }
    }
   },
   methods:{
   calcTotalTime(){
      
     }
   }
}
</script>

由于工作总时长是根据其他时长动态变化的。 因此我们可以将工作总时长定义在computed中。

下面我们来实现calcTotalTime这个方法:

//...忽略 
 calcTotalTime() {
  const {signIn,signOut} = this.form
  //只有用户选择了上班打卡时间和下班打卡时间 总时长才会有值
  if (signIn && signOut) {
    //使用moment.js获取到上班打卡时间
    const _signInTime = this.moment(signIn, 'HH:mm').valueOf()
    //使用moment.js获取到下班打卡时间
    const _signOutTime = this.moment(signOut, 'HH:mm').valueOf()
    //定义一个变量 获取上下班时间的时间戳间隔
    let betweenDate = 0;
    //然后我们需要判断 下班打卡时间是否小于上班打卡时间 如果小于则说明 用户选择的下班打卡时间是次日
    if (_signOutTime < _signInTime) {
      // 24小时 - 上班打卡时间 + 下班打卡时间 = 用户当日到次日所打卡的总时长
      betweenDate = Number((24 * 3600 * 1000) - _signInTime) + Number(_signOutTime)
    } else {
      //如果不是次日签到 则直接用 下班打卡时间 -  上班打卡时间  = 用户当日打卡总时长
      betweenDate = Number(_signOutTime - _signInTime)
    }
    // 接下来我们可以获取到总分钟数
    let totalMinutes = Math.floor(betweenDate / (60 * 1000))
    /*然后我们需要减去休息时间 得到用户真正的总工作时长
      由于用户可以选择多个休息区间 因此我们需要用到循环
     */
     const restTotalMinutes =  this.caclTotalRestTime()
    //判断总休息时长是不是大于等于上班工作总时长 大于则 总工作时长为0小时0分钟(产品说的)
    return restTotalMinutes >= totalMinutes?"0小时0分钟":`${Math.floor((totalMinutes-
    restTotalMinutes) / 60)}小时${((totalMinutes-restTotalMinutes) % 60)}秒`
  }
  return "0小时0分钟"
  },
  caclTotalRestTime(){
    const efficientRestTime = this.restTime.filter(i => i.startTime && i.endTime && i.startTime 
    != '00:00' && i.endTime != '00:00')
     let restTotalMinutes = 0;
      if (efficientRestTime.length > 0) {
        efficientRestTime.map(i => {
            let _beginDate = this.moment(i.startTime, 'HH:mm')
            let _endDate = this.moment(i.endTime, 'HH:mm')
            let betweenDates = 0;
            //这里我们同样需要判断休息结束时间是不是小于休息开始时间
            if (_endDate < _beginDate) {
              betweenDates = Number((24 * 3600 * 1000) - _beginDate
              ) + Number(_endDate)
            } else {
              betweenDates = _endDate - _beginDate
            }
            restTotalMinutes += Math.floor(betweenDates / (60 * 1000))
          })
    }
    return restTotalMinutes
  }

综上所示的方法即可算出实际工作的总时长了。当然这个需求不涉及到跨日的,还是比较简单的~~~ 但是挺有意思的 特此分享出来。 如果大家在工作中遇到类似需求,也可以以此作为借鉴。。。

最后

文章若有不足之处,还请大家批评指出。

感谢您观看此篇文章 希望能给个👍评论收藏三连!你的点赞就是我写作的动力。