使用 JavaScript 计算 2 个不同时间表的工作时数

Calculate hours worked from 2 different schedules with JavaScript

我有一名员工需要提供两餐,每餐可以有不同的开始时间和不同的用餐持续时间

我需要得到他工作的总时间,所以假设一顿饭是 60 分钟,另一顿饭也是 60 分钟,总共是 120 分钟, 但如果第二顿饭在第一顿饭的时间开始,则应该算作一次, 所以如果第二顿饭在第一顿饭后 10 分钟开始,那么总共应该是 70 分钟

var 膳食 = [{
    "mealStartTime":1478787000000,//上午 9:00
    "mealDuration": 60,
    "mealEndSearvingTime":1478790600000
}, {
    "mealStartTime":1478786400000,//上午 9:10
    "mealDuration": 60,
    "mealEndSearvingTime": 1478790000000
}]

// It might be a good idea to use a library like BigDecimal.js
// to prevent any float point errors, or use momentjs to calculate
// the distance between to times
function msToMins(ms) {
  return ms / 1000.0 / 60.0;
}

// It's important to note that this algo assumes that:
//   * Two meals never start at the same time
//   * Meals always end after meals that started before them
function timeWorked(meals) {
  // sort by start time
  const sortedMeals = meals.sort(m => m.mealStartTime);
  
  const result = meals.reduce((prev, curr) => {
    let duration = curr.mealDuration; // extract the current meal duration

    // if the previous meal overlaps with this one
    const mealsOverlap = prev.mealEndServingTime > curr.mealStartTime;
    if (mealsOverlap) {
      // calculate the distance when the previous end and this one ends
      // the previos meal duration was fully added in the previous cycle
      duration = msToMins(curr.mealEndServingTime - prev.mealEndServingTime);
    }
    
    // return the totalDuration accumulation, with the current meal
    return Object.assign({ totalDuration: prev.totalDuration + duration }, curr);
  }, { totalDuration: 0 }); // initialize with empty object
  
  return result.totalDuration;
}

const allMeals = [
  {
    mealStartTime: 1478787000000,
    mealDuration: 60,
    mealEndServingTime: 1478790600000
  }, 
  {
    mealStartTime: 1478786400000,
    mealDuration: 60,    
    mealEndServingTime: 1478790000000
  }
];

console.log(timeWorked(allMeals));

好吧,我的解决方案有点冗长。代码可能有点优化,但我认为这种方法是正确的。

我会将代码粘贴到此处,您可以查看此 jsfiddle 以查看它是否有效。不过打开控制台。

代码如下:

function getTotalWorkHours(meals){
    var punches = [], startCount = 0, endCount = 0, accountablePunchPairs = [], hoursWorked = 0;

  //// Populate an array of all punches ///
  meals.forEach(function(meal) {
    punches.push({
        type:'start',
      timestamp: meal.mealStartTime, 
      inEnglishPlease: new Date(meal.mealStartTime).toLocaleString()
    });
    punches.push({
        type: 'end',
      timestamp: meal.mealEndServingTime, 
      inEnglishPlease: new Date(meal.mealEndServingTime).toLocaleString()
    });
    });

  /// Sort the punches by time ///
  punches.sort(function(a, b){
    return a.timestamp - b.timestamp;
    });


  /// Filter out only the accountable punches.
  /// We will save the punches as an array of start/end pairs.
  /// Accountable punches are those that did not occur
  /// while the employee was busy with other meals
  punches.forEach(function(punch){
    if(punch.type === 'start'){
        if(++startCount - endCount === 1) accountablePunchPairs.push([punch]);
    }
    if(punch.type === 'end'){
        if(++endCount === startCount) {
        accountablePunchPairs[accountablePunchPairs.length-1][1] = punch;
      }
    }
  });

  /// Now just calculating the total hours based
  /// on the accountable punch pairs
  accountablePunchPairs.forEach(function(punchPair){
    hoursWorked += (punchPair[1].timestamp - punchPair[0].timestamp) / 3600000;
  });

  return hoursWorked;
}

https://jsfiddle.net/friedman5764/4nyv5um0/