简体   繁体   中英

How to calculate total hours?

I am trying to calculate total hours based on "employeeId". I couldn't figure out how to write logic for this. What is the best way to solve this problem?

Expected Result,

[
    {

        "employeeId": "105",
        "totalHours": "2:45"
    },
    {
        "employeeId": "777",
        "totalHours": "2:15"
    }
]

Response From Ajax Call

[
    {
        "employeeId": "105",
        "totalHours": "1:30"
    },
    {
        "employeeId": "777",
        "totalHours": "1:15"
    },
    {
        "employeeId": "105",
        "totalHours": "1:15"
    },
    {
        "employeeId": "777",
        "totalHours": "1:00"
    }
]

My Code

var jrr = new Array();
    Ext.Ajax.request({
      url: '/common/services/general/basicOperations/getDataByModelUsingGetMethod',
      method: 'GET',
      params : {
        actionId : 'payroll',
        dataJson : '{"aspectType":"Payroll Profile"}'
      },
      success: function(response){
        try{
          var response = response.responseText;
          var resObj = Ext.decode(response);
          for(var j = 0; j < resObj.data.length; j++)
              {
                 for(var k = 0; k < resObj.data[j].payrolltransactionDetail.length; k++) 
                 {
                    jrr.push(resObj.data[j].payrolltransactionDetail[k]);
                 }
              }
              console.log(JSON.stringify(jrr, null, 4));
        }
        catch(e){
          console.log(e);
        }
      },
      failure: function(response){
        deferred.reject("Error Fetching.");
      }
    });

Here is an implementation using js functional programming. You can transform the data to your desired output using just the reduce function. If you cannot change your query result using some kind of aggregation on the server side then you can implement something akin to the below.

 var input = [ { "employeeId": "105", "totalHours": "1:46" }, { "employeeId": "777", "totalHours": "1:15" }, { "employeeId": "105", "totalHours": "1:15" }, { "employeeId": "777", "totalHours": "1:00" } ] var obj = input.reduce( function(init, e){ //if aggregating init object doesn't have the employee then add the employeeId (key) and time (value) if (init[e["employeeId"]] == undefined){ init[e["employeeId"]] = { hours: parseInt(e["totalHours"].split(":")[0]), minutes: parseInt(e["totalHours"].split(":")[1]) }; init[e["employeeId"]].timeString = e["totalHours"]; return init; //otherwise add to the existing employeeId the hour and minute values, while remembering to carry the extra hour if minutes exceed 59. }else{ init[e["employeeId"]].hours += (parseInt(e["totalHours"].split(":")[0]) + Math.floor((init[e["employeeId"]].minutes + parseInt(e["totalHours"].split(":")[1]))/60)); init[e["employeeId"]].minutes = (init[e["employeeId"]].minutes + parseInt(e["totalHours"].split(":")[1]))%60; init[e["employeeId"]].timeString = init[e["employeeId"]].minutes > 9 ? init[e["employeeId"]].hours + ":" + init[e["employeeId"]].minutes : init[e["employeeId"]].hours + ":0" + init[e["employeeId"]].minutes; return init; } }, {}); var arr = []; for (var prop in obj) arr.push({employeeId: prop, totalHours: obj[prop].timeString}); console.log(arr); 

Here is an implementation. I think it's cleaner than some of the other answers:

function calc(data) {
    const seen = {};
    const result = [];

    data.forEach(item => {
        const id = item.employeeId;
        if (!seen.hasOwnProperty(id)) {
            seen[id] = result.length;
            result.push({
                employeeId: id,
                minutes: 0
            });
        }
        const idx = seen[id];
        const parts = item.totalHours.split(':');
        result[idx].minutes += (parseInt(parts[0], 10) * 60) + parseInt(parts[1]);
    });

    result.forEach(item => {
        const minutes = item.minutes;
        delete item.minutes;
        item.totalHours = Ext.String.leftPad(Math.floor(minutes / 60), 2, '0') 
                            + ':' + Ext.String.leftPad(minutes % 60, 2, '0');
    });

    return result;
}

console.log(calc([{
    "employeeId": "105",
    "totalHours": "1:30"
}, {
    "employeeId": "777",
    "totalHours": "1:15"
}, {
    "employeeId": "105",
    "totalHours": "1:15"
}, {
    "employeeId": "777",
    "totalHours": "1:00"
}]));

Add where at the top of the function:

var totalHours = 0;

and then inner loop is:

for(employee in resObj.data[j].payrolltransactionDetail) {
    totalHours += employee.totalHours;
}

and then you can use it however you deem appropriate after the outer loop. If you want to sum this per transactionDetail make sure you reset to 0 before the inner loop, and use after the inner loop.

//  Expecting input to be your custom object
var output={};
for(i=0;i<input.length;i++){
el = input[i];
a=output[el.id];
a.employeId=el.employeId;
a.totalHours=a.totalHours||"0:0";
b=el.totalHours.split(":");
c=a.totalHours.split(":");
b[0]=+b[0]+c[0];
if(b[1]+c[1]>60){
b[0]++;
}
b[1]=(+b[1]+c[1])%60;
a.totalHours=b.join(":");
}

The result is not exactly what youve expected. I dont wanted to search the employe id in the array each times:

{
105:{
   employeid:105;
   totalHours:"15:20";
 }
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM