Алгоритм вычисления времени

#javascript #time

#javascript #время

Вопрос:

Мне нужна помощь в алгоритме вычисления времени. Это не обычная временная операция, поэтому momentjs здесь не поможет.

Короче говоря, у меня есть время, которое я хочу сократить на другое время, например:

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

Общее время — это расчетное время для задачи, используемой в моем приложении, поэтому оно не рассчитано на 24 часа. Время 2 является результатом рабочего времени, например, если бы я работал над этой задачей 2 раза, сначала 30 минут, а затем 60 минут, то есть полтора часа.

В моем алгоритме я могу суммировать общее рабочее время по минутам, но я не могу реализовать вычисление сокращения из самого общего времени.

Здесь идет мой код с прокомментированными частями:

 // 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 amp;amp; 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);  

Версия для скрипки

Как вы можете видеть, пока «Пока все хорошо» (строка 41), кажется, все работает нормально. Моя проблема с вычислением после этого. Это беспорядок, и я могу его развить. Результат в случае сниппета должен быть 119:00 . Любая помощь будет оценена.

Комментарии:

1. почему бы не использовать epoc для вычисления? а затем отображать часы и минуты?

2. @NinaScholz я не знаю этого или как это сделать.

3. Это фактическая дата? Или просто представление часа? Если позже вы просто выполните простую математику. И манипулирование строками.

4. @Darkrum всего час представления. Это может быть 1:00 на 500:00 сегодняшний день само по себе не соответствует.

5. var s=(120*60 30 - (1*60 30)), M=Math.floor(s/60), S=M*60-s; [M,S]

Ответ №1:

Это можно было бы сделать проще, но поскольку это ваш код, и его важно изучить, я просто отредактировал и добавил еще несколько строк с комментариями. Надеюсь, это вам поможет.

     // 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 amp;amp; 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);  

Комментарии:

1. Математика времени — это сука, я действительно не понимаю, ха-ха. Спасибо.

Ответ №2:

При манипулировании временем почти всегда рекомендуется делать это с точностью до миллисекунд.

 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());  

РЕДАКТИРОВАТЬ 1

Я забыл включить days . В моей настройке дни масштабируются бесконечно (потому что я не хочу портить странные месяцы, такие как февраль или високосные годы).