Home > OS >  Calculate total duration out of specified time duration Node Js
Calculate total duration out of specified time duration Node Js

Time:09-22

I am calculating Over Time from work start time & work End time.

We need to calculate Over Time that does not include regular work Timings.

Example: Regular Work Timings is 10:00 AM to 07:00 PM

Over Time need to get from these timings: Start Work Hour: 13-09-2021 08:00 End Work Hour: 15-09-2021 20:00

We need to calculate total hours outside of 10:00 AM to 07:00 PM from Start Work Hour: 13-09-2021 08:00 & End Work Hour: 15-09-2021 20:00

So, here Total OT would be: 32 Hour

What I have tried?

If work Start time and End time in the same day, OT calculation works fine with the below code.

Start Hour : 15-09-21 08:00 End Hour : 15-09-21 21:00


getWorkHours.forEach((workhourOT) => {
            try {
        
              //  --------------------------------------
              let StartWorkHour = moment(
                workhourOT.starttime,
                "DD-MM-YYYY hh:mm:ss"
              );
              let TodayOfficeStartDate =
                moment(StartWorkHour).format("DD-MM-YYYY");

              let StartOfficeHour = moment(
                `${TodayOfficeStartDate}`   ` 10:00:00`,
                "DD-MM-YYYY hh:mm:ss"
              );

              const diffInMillisecondsBeforeOfficeHour = Math.abs(
                new Date(StartWorkHour) - new Date(StartOfficeHour)
              );
              let OTBeforeOffice =
                diffInMillisecondsBeforeOfficeHour / 1000 / 3600;
              console.log(OTBeforeOffice);
              let EndtWorkHour = moment(
                workhourOT.endtime,
                "DD-MM-YYYY hh:mm:ss"
              );

              let TodayOfficeEndDate =
                moment(EndtWorkHour).format("DD-MM-YYYY");

              let EndOfficeHour = moment(
                `${TodayOfficeEndDate}`   ` 19:00:00`,
                "DD-MM-YYYY hh:mm:ss"
              );

              const diffInMillisecondsAfterOfficeHour = Math.abs(
                new Date(EndtWorkHour) - new Date(EndOfficeHour)
              );
              let OTAfterOffice =
                diffInMillisecondsAfterOfficeHour / 1000 / 3600;
              console.log(OTAfterOffice);
              let totalWORKOT = OTAfterOffice   OTBeforeOffice;

              data["TotalWork_OT"] = totalWORKOT.toFixed(1);
            } catch (error) {
              console.log(error);
            }
          });


OutPut is

{

    "TotalWork_OT": "4.0",

}

CodePudding user response:

There is a lot of logic missing from the OP to achieve the required result. Consider an approach where a workHours object {startTime, endTime} is enhanced with an overtime property.

For each workHours object the following cases need to be addressed, where nominal start and end are normal hours (10:00 to 19:00):

  1. start and end before nominal start
  2. start and end after nominal start
  3. start before, end during nominal hours
  4. start during and end after nominal hours
  5. start and end during nominal hours

In addition, it needs to account for times going over midnight and likely also skip weekends.

The OP assumes work starts before nominal start and ends after nominal end, so the below example does the same. So it only addresses one of the above cases, and has virtually no error handling, but it should provide an idea of what's required to do the job.

It takes a work hours object and returns a new object augmented with an overtime property and the overtime hours in the range. It only deals with whole hours and where work start and end are before and after nominal start and end respectively.

Each helper function can be extended with required additional functionality to handle the other cases and deal with partial hours (maybe round to 15 minute increments).

// Parse timestamp in DD-MM-YYYY HH:mm format
// Values after day are optional and default to zero (0)
function parseWorkHour(wh) {
  let [D, M, Y, H, m, s] = wh.split(/\W/);
  return new Date(Y, M-1, D, H||0, m||0, s||0);
}

// Format date as DD-MM-YYYY HH:mm
function formatWorkHour(date) {
  let z = n => ('0' n).slice(-2);
  return `${z(date.getDate())}-${z(date.getMonth() 1)}-`  
         `${date.getFullYear()} ${z(date.getHours())}:`  
         `${z(date.getMinutes())}`;
}

// Return true if date1 and date2 are same day
function areSameDay(d1, d2) {
  return !isNaN(d1) && !isNaN(d2) &&
         d1.getFullYear() == d2.getFullYear() &&
         d1.getMonth() == d2.getMonth() &&
         d1.getDate() == d2.getDate();
}

// Given workhours object {startTime, endTime} return
// array of daily workHours objects for input object range
function getDailyWorkHours(who) {
  let start = parseWorkHour(who.startTime);
  let end = parseWorkHour(who.endTime);
  let dailyWorkHours = [];
  // No validation (e.g. start > end) so guard against infinite loop
  let i = 10;
  
  while (!areSameDay(start, end) && --i) {
    let temp = new Date(start);
    temp.setHours(23,59,59,999);
    dailyWorkHours.push({
      startTime: formatWorkHour(start),
      endTime: formatWorkHour(temp)
    });
    temp.setHours(24,0,0,0);
    start = temp;
  }
  dailyWorkHours.push({
    startTime: formatWorkHour(start),
    endTime: formatWorkHour(end)
  });
  return dailyWorkHours;
}

// Get overtime from workHours object {startTime, endTime}
// startTime and endTime must be same day.
// Overtime is before 10:00 and after 19:00
function getOvertime(who) {
  let workStart = parseWorkHour(who.startTime);
  let workEnd = parseWorkHour(who.endTime);
  let officeStart = new Date( workStart);
  officeStart.setHours(10,0,0,0);
  let officeEnd = new Date( workEnd);
  officeEnd.setHours(19,0,0,0);
  let ot = (officeStart - workStart) / 3.6e6  
           (workEnd - officeEnd) / 3.6e6;
  // Round to nearest hour
  return Math.round(ot);         
}

// Given work hours array [{startTime,endTime}], calculate how
// much overtime has been worked, 
// i.e. time before officeStart (10:00) and officeEnd (19:00)
function tallyOvertime(workHoursArray) {
  let result = [];
  
  workHoursArray.forEach( who => {
    let dailyWorkHours = getDailyWorkHours(who);
    let overTime = dailyWorkHours.reduce((ot, who) => {
      ot  = getOvertime(who);
      return ot;
    }, 0);
    result.push({
      startTime:who.startTime,
      endTime:who.endTime,
      overTime:overTime
    });
  });
  return result;
}

let data = [
  // Same day - 5 hrs
  {startTime:'20-09-2021 06:00', endTime:'20-09-2021 20:00'},
  // Over midnight - 20
  {startTime:'20-09-2021 06:00', endTime:'21-09-2021 20:00'},
  // OP example - 33
  {startTime:'13-09-2021 08:00', endTime:'15-09-2021 20:00'}
];

console.log(tallyOvertime(data));

In the OP there is:

We need to calculate total hours outside of 10:00 AM to 07:00 PM from Start Work Hour: 13-09-2021 08:00 & End Work Hour: 15-09-2021 20:00

So, here Total OT would be: 32 Hour

Which is incorrect. The breakdown is as follows:

  1. 13-09-2021 08:00 to 10:00 is 2 hours
  2. 13-09-2021 19:00 to 24:00 is 5 hours
  3. 14-09-2021 00:00 to 10:00 is 10 hours
  4. 14-09-2021 19:00 to 24:00 is 5 hours
  5. 15-09-2021 00:00 to 10:00 is 10 hours
  6. 15-09-2021 19:00 to 20:00 is 1 hour

which totals 33 hours, not 32.

CodePudding user response:

I have done something like this. work Start date: 18-09-21 08:00 work End Date: 20-09-21 20:00

  1. get OT for the work start date to midnight the same day. start: 18-09-21 08:00 ---- end: 18-08-21 24:00
  2. get OT starting from the start day of the work end date to work end time. start: 20-09-21 00:00 --- end: 20-09-21 20:00
  3. on every full day of working we get 15 Hour Overtime excluding regular working hours. so we can multiply the total full day OT with 15. and sum all three results.

OT Function

async function calculateWorkOverTime(TimingArr) {
  for (OTI = 0; OTI < TimingArr.length; OTI  ) {
    try {

      
      let StartWorkHour = moment(
        TimingArr[OTI].starttime,
        "DD-MM-YYYY hh:mm:ss"
      );
      let TodayOfficeStartDate = moment(StartWorkHour).format("DD-MM-YYYY");

      let StartOfficeHour = moment(
        `${TodayOfficeStartDate}`   ` 10:00:00`,
        "DD-MM-YYYY hh:mm:ss"
      );

      const diffInMillisecondsBeforeOfficeHour = Math.abs(
        new Date(StartWorkHour) - new Date(StartOfficeHour)
      );
      let OTBeforeOffice = diffInMillisecondsBeforeOfficeHour / 1000 / 3600;
      // console.log(OTBeforeOffice);
      let EndtWorkHour = moment(TimingArr[OTI].endtime, "DD-MM-YYYY hh:mm:ss");

      let TodayOfficeEndDate = moment(EndtWorkHour).format("DD-MM-YYYY");

      let EndOfficeHour = moment(
        `${TodayOfficeEndDate}`   ` 19:00:00`,
        "DD-MM-YYYY hh:mm:ss"
      );

      const diffInMillisecondsAfterOfficeHour = Math.abs(
        new Date(EndtWorkHour) - new Date(EndOfficeHour)
      );
      let OTAfterOffice = diffInMillisecondsAfterOfficeHour / 1000 / 3600;

      let totalWORKOT = OTAfterOffice   OTBeforeOffice;

      return totalWORKOT;
    } catch (error) {
      return error;
    }
  }
}

var OT = "";
          for (OTArr = 0; OTArr < getWorkHours.length; OTArr  ) {
            let StartTimingWork = moment(
              getWorkHours[OTArr].starttime,
              "DD-MM-YYYY hh:mm:ss"
            );

            let TodayStartTiming = moment(StartTimingWork).format("DD-MM-YYYY");

            let EndTimingWork = moment(
              getWorkHours[OTArr].endtime,
              "DD-MM-YYYY hh:mm:ss"
            );
            console.log(getWorkHours);
            let TodayEndTiming = moment(EndTimingWork).format("DD-MM-YYYY");
            if (TodayEndTiming === TodayStartTiming) {
              let getOTFROMTIMING = await otcontroller.calculateWorkOverTime(
                getWorkHours
              );
              OT = getOTFROMTIMING;
              data["WOT"] = OT;
            } else {
              // var workstartDate = moment(TodayEndTiming, "DD-MM-YYYY");
              var workstartDate = StartTimingWork;
              let currentDayMidNight = moment(workstartDate).endOf("day");
              let ArrOfTiming = [
                {
                  starttime: workstartDate,
                  endtime: currentDayMidNight,
                },
              ];

              let getOTFROMTIMING = await otcontroller.calculateWorkOverTime(
                ArrOfTiming
              );
              console.log(getOTFROMTIMING);

              var workendDate = EndTimingWork;
              let startOfWorkEndDate = moment(workendDate).startOf("day");
              // console.log(workendDate);
              // console.log(startOfWorkEndDate);
              let ArrOfTimingEnd = [
                {
                  starttime: startOfWorkEndDate,
                  endtime: workendDate,
                },
              ];
              let getOTFROMTIMINGlastDay =
                await otcontroller.calculateWorkOverTime(ArrOfTimingEnd);
              console.log(getOTFROMTIMINGlastDay);
              // var workendDate = EndTimingWork;
              // console.log(workstartDate);
              console.log("workendDate");
              console.log(workendDate);
              console.log(workstartDate);
              console.log("workstartDate");
              var result = workendDate.diff(workstartDate, "days");
              console.log(result);
              console.log("result");

              let wholeDaysOT = (result - 1) * 15;
              console.log(
                wholeDaysOT   getOTFROMTIMINGlastDay   getOTFROMTIMING
              );
              let TotalWorkOverTime =
                wholeDaysOT   getOTFROMTIMINGlastDay   getOTFROMTIMING;
              data["WOT"] = TotalWorkOverTime.toFixed(1);
            }
          }

  • Related