0

I need a helping hand in a time calculation algorithm. It is not a usual time operation, so momentjs won't help here.

In short, I have a time amount which I want to reduce another time amount, e.g.:

 120:30 // total time
-  1:30 // time 2
 119:00 // result

The total time is an estimated time for a task used in my app, so it isn't a 24 hours based time. The time 2 is a result of the working time, like if I worked 2 times on this task, first being 30 minutes and secund 60 minutes, so one hour and a half.

In my algorithm I can sum to total working time by minutes, but I can't implement the reduction calculation from the total time itself.

Here goes my code with commented parts:

// Types = 1- Start, 2- Stop

var estimatedTime = "120:30", // One hundred twenty hours and thirty minutes
    timeHistory = [{
      type: 1,
      time: new Date(2016, 9, 10, 1, 0, 0) // Start action
    }, {
      type: 2,
      time: new Date(2016, 9, 10, 1, 30, 0) // Adds 30 minutes since last history
    },  {
      type: 1,
      time: new Date(2016, 9, 10, 1, 40, 0) // Start again after 10 minutes interval
    },  {
      type: 2,
      time: new Date(2016, 9, 10, 2, 40, 0) // Adds 60 minutes since last history
    }];
   
// Total of 90 minutes of work

//----------------------------------
// Calculation algorithm

var totalTime = 0,
    lastTime = null;

timeHistory.forEach(function(h) {
  // Sums to totalTime the diff between last "Start" and the current "Stop" time
  if (lastTime && h.type != 1) {
    totalTime+= h.time.getTime() - lastTime.getTime();
  }

  lastTime = h.time;
});

// If time is running (type 1 = Start), sums the current time
if (timeHistory[timeHistory.length - 1].type == 1) {
  totalTime+= (new Date()).getTime() - lastTime.getTime();
}

var t1 = Math.floor(totalTime / 60000); // Get total minutes
console.log(t1); // So far so good
    
var estTime = estimatedTime.split(":").map(Number), // Getting time hours and minutes as numbers
    resultMinutes = 60 - (t1 % estTime[1]),
    resultHours = (Math.floor(t1 / estTime[1]) > 0 ? (estTime[0] - Math.floor(t1 / estTime[1])) : 0);
    
if (resultMinutes == 60) {
  resultHours+= 1;
  resultMinutes = 0;
}
    
console.log("Result:", resultHours + ":" + resultMinutes);

Fiddle version

As you can see, until "So far so good"(line 41) everything seems to be working fine. My problem is with the calc after that. It is a mess and I can evolve it. The result in the snippet case should be 119:00. Any help would be appreciated.

5
  • why not use epoc for calculating? and render then hours and minutes? Commented Oct 10, 2016 at 14:38
  • @NinaScholz I don't know it or how to do it. Commented Oct 10, 2016 at 14:39
  • Is this a actual date? Or just a hour representation? If the later you good just do simple math. And string manipulation. Commented Oct 10, 2016 at 14:44
  • @Darkrum just a hour representation. It can be 1:00 to 500:00 date itself doesn't metters. Commented Oct 10, 2016 at 14:46
  • var s=(120*60+30 - (1*60+30)), M=Math.floor(s/60), S=M*60-s; [M,S] Commented Oct 10, 2016 at 15:27

2 Answers 2

1

This could be done more simply but since it's your code, and it's important to learn I have simply edited and added few more lines with comments. Hope this helps you.

    // Types = 1- Start, 2- Stop

    var estimatedTime = "120:30", // One hundred twenty hours and thirty minutes
        timeHistory = [{
          type: 1,
          time: new Date(2016, 9, 10, 1, 0, 0) // Start action
        }, {
          type: 2,
          time: new Date(2016, 9, 10, 1, 30, 0) // Adds 30 minutes since last history
        },  {
          type: 1,
          time: new Date(2016, 9, 10, 1, 40, 0) // Start again after 10 minutes interval
        },  {
          type: 2,
          time: new Date(2016, 9, 10, 2, 40, 0) // Adds 60 minutes since last history
        }];
       
    // Total of 90 minutes of work

    //----------------------------------
    // Calculation algorithm

    var totalTime = 0,
        lastTime = null;

    timeHistory.forEach(function(h) {
      // Sums to totalTime the diff between last "Start" and the current "Stop" time
      
 if (lastTime && h.type != 1) {
        totalTime+= h.time.getTime() - lastTime.getTime();
      }


      lastTime = h.time;
    });

totalTimeInMins = totalTime/(1000*60); // Get total minutes of work done

console.log(totalTimeInMins + " mins of work" );

var estTime = estimatedTime.split(":").map(Number); // Getting time hours and minutes as numbers

var estTimeInMins = estTime[0]*60+estTime[1] ;//converting esitmated time to minutes
 var resultTimeInMins = estTimeInMins - totalTimeInMins ; //calculating result time
var resultHours = Math.floor(resultTimeInMins/60); //getting number of hours. Math.floor is rounding off to lower integer
var resultMinutes = resultTimeInMins%60; //calculating number of minutes. This is like getting the remainder.


console.log("Result:", resultHours + ":" + resultMinutes);

Sign up to request clarification or add additional context in comments.

1 Comment

Time math is a bitch, I really don't get it right haha. Thank you.
1

When manipulating time it's almost always a good idea to do it on a millisecond base.

var Time = (function () {
    function Time(time) {
        if (time === void 0) { time = 0; }
        this.time = time;
    }
    Time.prototype.setSeconds = function (seconds) {
        if (seconds === void 0) { seconds = 0; }
        this.time += (seconds * 1000);
        return this;
    };
    Time.prototype.setMinutes = function (minutes) {
        if (minutes === void 0) { minutes = 0; }
        this.time += ((minutes * 60) * 1000);
        return this;
    };
    Time.prototype.setHours = function (hours) {
        if (hours === void 0) { hours = 0; }
        this.time += (((hours * 60) * 60) * 1000);
        return this;
    };
    Time.prototype.setDays = function (days) {
        if (days === void 0) { days = 0; }
        this.time += ((((days * 24) * 60) * 60) * 1000);
        return this;
    };
    Time.prototype.getTime = function (toString) {
        if (toString === void 0) { toString = false; }
        var t = this.time;
        var d = new Date(Math.abs(t));
        var sub = this.time < 0;
        d.setHours(d.getHours() - 1);
        d.setFullYear(0);
        var time = {
            days: Math.floor(Math.abs(this.time) / (((24 * 60) * 60) * 1000)),
            hours: d.getHours(),
            minutes: d.getMinutes(),
            seconds: d.getSeconds(),
            milliseconds: d.getMilliseconds(),
            sub: sub
        };
        //Returns in the format "DAYS:HOURS:MINUTES:SECONDS"
        if (toString === true) {
            return (sub ? '-' : '') +
                Math.abs(time.days) +
                ':' +
                Math.abs(time.hours) +
                ':' +
                Math.abs(time.minutes) +
                ":" +
                Math.abs(time.seconds);
        }
        else {
            return time;
        }
    };
    return Time;
}());
var t1 = new Time();
var t2 = new Time();
t1
    .setMinutes(357)
    .setHours(1200);
t2
    .setHours(-1)
    .setMinutes(-30);
var t3 = new Time(t1.time + t2.time);
console.log("t1", t1.getTime(true));
console.log("t2", t2.getTime(true));
console.log("t3", t3.getTime(true));
console.log("t3", t3.getTime());

EDIT 1

I forgot to includes days. In my setup days scale indefinitely (because i don't want to mess weird months like February or leap years).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.