获取另一个时间段内特定时间段的小时数

时间:2018-05-21 11:42:19

标签: javascript algorithm typescript

非常努力让我痛苦一个场景:

餐厅的服务员每小时收入15美元,但在21.00和02.30之间,他获得额外3美元/小时的报酬。现在我拥有的是“开始”#39;并且'结束'作为日期 - 对象的转变,我想计算在转移中多少小时的额外付费期间(如果有的话)。(记住转变的开始和结束时间可以是任何东西 - 并且它得到的bc很难)

我通过使用大量的if语句使其工作,但这绝对不是正确的做法。我在这里添加了我的代码link但是它只是一团糟所以你知道(在代码fui中有两个不同的时间段和额外的代价)。任何人都有更好的计算方法的想法?(任何可以在这里帮助的类?)

static calculateShiftSalary(shift: Shift, employee: Employee): Shift {
    const extraPaidStart = 22
    const extraPaidEnd= 2.5 // meaning 02.30 o'clock -of the next day here

    let start:Date = shift.startDate
    let end:Date = shift.endDate

    let extraHours:number = 
          getNumberOfExtraPaidHours(start,end,extraPaidStart,extraPaidEnd)
}

所以如果U' d在20.00和23.30之间转换 - >' extraHours' = 1,5如果转换在23.00和02.00之间 - > extraHours = 3h

extraPaidStart和extraPaidEnd可以更改为Date ofc,如果有任何帮助(y)

1 个答案:

答案 0 :(得分:1)

让我们先看看最简单的案例:我们的工人只工作一天。一个时间表是夜晚的额外时间看起来像这样:

extra paid ---|-- regular paying ---------|---- extra paid ---
      |--------- working time -----------------------------|
      |--- 1 -------|--------------- 2 ----------------|---- 3 ---|

只是跨越一天的额外时间实际上更简单:

|----------- regular paying -------|------ extra paid ----|----|
    |------ working time -----------------|
    |-----  1 -----------------------------|- 2 -|

所以我们只需计算工人工作的三个不同范围,所有单位都在几分钟内:

 function paymentRange(payment: number, start: number, end: number) {
    return function calculatePayment(startWorking: number, endWorking: number) {
      if(start < end) { 
        const rangeStart = Math.max(start, startWorking);
        const rangeEnd = Math.min(end, endWorking);
        return Math.max(rangeEnd - rangeStart, 0) / 60 * payment;
    } else {
       const morning =  Math.max(end - startWorking, 0);
       const evening = Math.max(endWorking - start, 0)
       return (morning + evening) / 60 * payment;
  }
 }
}

现在我们只需要一种方法来组合多笔付款:

 function combinedPayment(...payments) {
   return (start, end) => payments.reduce((sum, payment) => sum + payment(start, end), 0);
 }

为了获得一天的付款,我们可以这样做:

 const calculatePayment = combinedPayment(
   paymentRange(3/*$*/, 22/*h*/ * 60, 2/*h*/ * 60 + 30/*min*/),
   paymentRange(15/*$*/, 0/*min*/, 24/*h*/ * 60)
);

 // If he worked from 1h to 22h:
calculatePayment(1/*h*/ * 60, 22/*h*/ * 60)

现在我们只需要将日期范围划分为几天,并计算日期的付款:

 const dateToMins = date => date.getHours() * 60 + date.getMinutes();

const toWholeDay = date => new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
const min = (a, b) => new Date(Math.min(+a, +b));
const max = (a, b) => new Date(Math.max(+a, +b));

 function paymentForDateRange(payment, start: Date, end: Date) {
  let pay = 0;
  let today = toWholeDay(start);
  while(+today < +end) {
    const nextDay = new Date(today + 1000 * 60 * 60 * 24);
    const startWorking = max(start, today);
    const endWorking = min(end, nextDay);
    pay += payment(dateToMins(startWorking), dateToMins(endWorking));
   today = nextDay;
  }
  return pay;
}

所以我们终于可以做到:

paymentForDateRange(calculatePayment, new Date(), new Date())

PS:我无法测试它的每一部分,它可能无法完全发挥作用