使用 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;
}
我有一名员工需要提供两餐,每餐可以有不同的开始时间和不同的用餐持续时间
我需要得到他工作的总时间,所以假设一顿饭是 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;
}