Yams Yams - 5 days ago 4
Javascript Question

Not able to calculate total hours

I am new to JavaScript. We have a code to add total hours based on "employee id". Below code showing correct result for "excessTime". But for "totalHours" it is showing "NaN". Does anyone know why it is showing "NaN" while adding "totalHours" and How to fix it?

<!DOCTYPE html>
<html>
<body>
<script>
var input = [
{
"employeeId": "101",
"totalHours": "1:46",
"excessTime": "2:15"
},
{
"employeeId": "102",
"totalHours": "1:15",
"excessTime": "1:30"
},
{
"employeeId": "101",
"totalHours": "1:15",
"excessTime": "3:00"
},
{
"employeeId": "102",
"totalHours": "1:00",
"excessTime": "2:15"
}
]

var obj = input.reduce( function(init, e){
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"];
init[e["employeeId"]] = {hrs: parseInt(e["excessTime"].split(":")[0]),mns: parseInt(e["excessTime"].split(":")[1])};
init[e["employeeId"]].excessString = e["excessTime"];
return init;
} 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;

init[e["employeeId"]].hrs += (parseInt(e["excessTime"].split(":")[0]) + Math.floor((init[e["employeeId"]].mns + parseInt(e["excessTime"].split(":")[1]))/60));
init[e["employeeId"]].mns = (init[e["employeeId"]].mns + parseInt(e["excessTime"].split(":")[1]))%60;
init[e["employeeId"]].excessString = init[e["employeeId"]].mns > 9 ? init[e["employeeId"]].hrs + ":" + init[e["employeeId"]].mns : init[e["employeeId"]].hrs + ":0" + init[e["employeeId"]].mns;
return init;
}
}, {});

var arr = [];
for (var prop in obj) arr.push({employeeId: prop, totalHours: obj[prop].timeString, excessTime: obj[prop].excessString});
console.log(arr);
</script>
</body>
</html>


Output:

[
{
"employeeId": "101",
"totalHours": "NaN:0NaN",
"excessTime": "5:15"
},
{
"employeeId": "102",
"totalHours": "NaN:0NaN",
"excessTime": "3:45"
}
]

Answer

You are attempting to assign values to the hours and minutes properties, but they are undefined. You need to assign them to their hours and minutes respectively in your first if statement:

init[e["employeeId"]].hours = parseInt(e["totalHours"].split(":")[0]);
init[e["employeeId"]].minutes = parseInt(e["totalHours"].split(":")[1]);

All together looks like this:

var input = [
    {
        "employeeId": "101",
        "totalHours": "1:46",
        "excessTime": "2:15"
    },
    {
        "employeeId": "102",
        "totalHours": "1:15",
        "excessTime": "1:30"
    },
    {
        "employeeId": "101",
        "totalHours": "1:15",
        "excessTime": "3:00"
    },
    {
        "employeeId": "102",
        "totalHours": "1:00",
        "excessTime": "2:15"
    }
]

    var obj = input.reduce( function(init, e){
    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"];
         init[e["employeeId"]] = {hrs: parseInt(e["excessTime"].split(":")[0]),mns: parseInt(e["excessTime"].split(":")[1])};
         init[e["employeeId"]].excessString = e["excessTime"];
         init[e["employeeId"]].hours = parseInt(e["totalHours"].split(":")[0]);
         init[e["employeeId"]].minutes = parseInt(e["totalHours"].split(":")[1]);
         return init;
      } 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;

         init[e["employeeId"]].hrs += (parseInt(e["excessTime"].split(":")[0]) + Math.floor((init[e["employeeId"]].mns + parseInt(e["excessTime"].split(":")[1]))/60));
         init[e["employeeId"]].mns = (init[e["employeeId"]].mns + parseInt(e["excessTime"].split(":")[1]))%60;
         init[e["employeeId"]].excessString = init[e["employeeId"]].mns > 9 ? init[e["employeeId"]].hrs + ":" + init[e["employeeId"]].mns : init[e["employeeId"]].hrs + ":0" + init[e["employeeId"]].mns;
         return init;
      }
  }, {});

var arr = [];
for (var prop in obj) arr.push({employeeId: prop, totalHours: obj[prop].timeString, excessTime: obj[prop].excessString});
console.log(arr);

Result:

  [{
        "employeeId": "101",
        "totalHours": "3:01",
        "excessTime": "5:15"
    }, {
        "employeeId": "102",
        "totalHours": "2:15",
        "excessTime": "3:45"
    }]

JSFiddle: https://jsfiddle.net/v7eckcny/

Comments