Add hours as Moment.Js

Asked

Viewed 1,554 times

0

I have a table with the following fields:

inserir a descrição da imagem aqui

However I do not want to work with date and time together, I wonder if there is the possibility of Moment.js adding only the hours, without necessarily needing the date in the variable obtained.

Well, when I submit my query I bring my hours based on the dates registered in the bank.

inserir a descrição da imagem aqui

My controller is currently like this:

public function get()
{
    $user = $_SESSION['nome'];

    $this->load->model('trackerModel');
    $query = $this->trackerModel->get($user)->result_array();

    foreach($query as $element){
        $result[$element['date']][] = $element;

    }   

    $data = [];
    foreach($result as $key=>$value){
        $data[] = [
            'date'=> $key,
            'item' => $value
        ];
    }
    echo json_encode($data);
}

And my JSON, like this:

[{"date":"26-08-2019","item":[{"id":"78","hrStart":"11:09:00","hrEnd":"12:09:00","hrWork":"01:00:00","nome_user":"Diego ","date":"26-08-2019","cliente":"Marcelo","projeto":"Aplicativo Mobile","pacote":"Aplicativo Mobile","type":"Non-Billable","descri":"","hrTotal":""},{"id":"82","hrStart":"04:00:00","hrEnd":"07:00:00","hrWork":"03:00:00","nome_user":"Diego ","date":"26-08-2019","cliente":"Carlos","projeto":"TimeSheet","pacote":"TimeTrack","type":"programa\u00e7\u00e3o","descri":"","hrTotal":""}]}]

Hence my doubt, I want to take these hrWork and add, but I just want the total result of each date, so I can show the user how much he worked per day. This is possible?

  • const Endtime = Moment(hrStart, 'HH:mm:ss'). add(durationInMinutes, 'minutes'). format('HH:mm');

2 answers

4


First we need to understand two important concepts. Consider the two sentences below:

  • I started working at 8 am
  • today I worked for 8 hours straight

In the first case, "8 hours" refers to timetable (a specific moment of the day). It’s okay that it needs "morning" not to be ambiguous (it could be 8 at night), but the fact is that it’s referring to a specific moment.

In the second case, "8 hours" refers to duration (an amount of time). It is not said what hours I started working. It is only the amount of time with no relation to schedules.

These two concepts are not the same thing. A time (hour, minute, second, fractions of a second) refers to a specific moment of a day. Durations are just amounts of time, which exist by themselves, without being tied to a specific date and time.

What confuses is the fact that both (both times and durations) use exactly the same words (days, hours, minutes, etc.), and are often written in the same way (a clock shows "08:00:00" when it is 8 am, a stopwatch shows "08:00:00" when the time count reaches eight o'clock).

Another point that can - erroneously - make us think that times and durations are the same thing is that, although they are different concepts, they may be related. If I calculate the difference between two dates and/or times, the result is a duration (knowing the date/time that started and ended, I can calculate how long it lasted), and if I add a date/time with a duration, the result is another date/time (knowing the date/time that started and how long it lasted, I can calculate the date/time that ended).


That said, their fields hrStart and hrEnd are times (the time when started and finished the work), while the field hrWork is a duration (the amount of time worked).

So the first point is that hrWork should not be kept as a TIME in the database, because it’s not a schedule. Perhaps it should be stored as a number, containing the total amount of minutes (or seconds), for example. But anyway, this is a problem aside, let’s go to the calculation itself.

Fortunately, Moment.js supports durations, then just get them from your JSON and add them up. To show the result in a more user-friendly format, you can download the version with locales:

let json = [{"date":"26-08-2019","item":[{"id":"78","hrStart":"11:09:00","hrEnd":"12:09:00","hrWork":"01:00:00","nome_user":"Diego ","date":"26-08-2019","cliente":"Marcelo","projeto":"Aplicativo Mobile","pacote":"Aplicativo Mobile","type":"Non-Billable","descri":"","hrTotal":""},{"id":"82","hrStart":"04:00:00","hrEnd":"07:00:00","hrWork":"03:00:00","nome_user":"Diego ","date":"26-08-2019","cliente":"Carlos","projeto":"TimeSheet","pacote":"TimeTrack","type":"programa\u00e7\u00e3o","descri":"","hrTotal":""}]}];

let duracaoTotal = moment.duration(0);
// percorrer os itens
json.forEach(obj => {
    obj.item.forEach(i => {
        duracaoTotal.add(moment.duration(i.hrWork));
    });
});
// usar o locale "pt" (português)
console.log(`Total: ${duracaoTotal.locale("pt").humanize()}`);

// ou formate o valor manualmente (nesse caso não precisa da versão com locales)
console.log(duracaoTotal.hours().toString().padStart(2, '0') + ':' +
            duracaoTotal.minutes().toString().padStart(2, '0') + ':' +
            duracaoTotal.seconds().toString().padStart(2, '0'));

// também é possível obter o total em minutos
console.log(duracaoTotal.asMinutes()); // 240
<script src="https://momentjs.com/downloads/moment-with-locales.min.js"></script>

Unfortunately there is still no method similar to format for durations (as there is for dates), then you can use the version with locales to display to the user in a more user-friendly format, or manually format if you need a specific format.

But to record in the bank, it is better to keep a single numerical value (like the total of minutes, for example). In the above case, the total (returned by the method asMinutes()) is 240 minutes (equivalent to a duration of 4 hours), and this value could be stored in a numerical field (to restore the duration, just do moment.duration(240, 'minutes'), for example). Use a type TIME (that represents a time) to save a duration is not ideal.


The code above makes a loop and sums up everything you have in JSON. But in your case, you want to separate by date, so just make a small adaptation:

// versão simplificada, com os campos que vou usar, apenas para fins didáticos
let json = [
    {"date" : "26-08-2019",
     "item" : [
         {"hrWork":"01:00:00","date":"26-08-2019"}, 
         {"hrWork":"03:00:00","date":"26-08-2019"}
     ]
    },
    {"date" : "27-08-2019",
     "item" : [
         {"hrWork":"02:00:00","date":"27-08-2019"}, 
         {"hrWork":"01:30:00","date":"27-08-2019"}
     ]
    }
];

let totais = {};
// percorrer os itens
json.forEach(obj => {
    obj.item.forEach(i => {
        if (! totais[i.date]) {
            totais[i.date] = moment.duration(0);
        }
        totais[i.date].add(moment.duration(i.hrWork));
    });
});

Object.keys(totais).forEach(d => {
    let duracaoTotal = totais[d];
    console.log(`Total do dia ${d}: ` +
                duracaoTotal.hours().toString().padStart(2, '0') + ':' +
                duracaoTotal.minutes().toString().padStart(2, '0') + ':' +
                duracaoTotal.seconds().toString().padStart(2, '0'));
});
<script src="https://momentjs.com/downloads/moment.min.js"></script>

Note that now I have not used the version with locales, and yes the moment.min.js, because I didn’t use the method humanize (instead I formatted the value manually).

And now an object has been created totais, whose keys are the dates and values are the respective totals of each day.

2

You can calculate the difference in minutes between the "two hours" and then add the difference in the new time.

// hora inicial
var hrStart = '10:00';
// hora final
var hrEnd = '11:02';
// hora que você vai somar
var hfFoo = '20:00';

// Calcula a diferença em minutos entre os dois tempos 
var diffInMinutes = moment(hrEnd,"HH:mm").diff(moment(hrStart,"HH:mm"), 'minutes');

// Adiciona os minutos na hora desejada
var totalTime = moment(hfFoo, 'HH:mm').add(diffInMinutes, 'minutes').format('HH:mm');

console.log(totalTime);

// 21:02
  • Right, but my hours already comes formatted from the bank... I wanted to add them to the Moment if possible

  • Formatted as?

  • they come in the format hh:mm, but wanted to make a sum of them, inside a for, would have as?

  • Yes, I’ll change the answer.

  • All right, I’ll wait here, thank you!

  • @Diêgocorreiadeandrade checks if now solves your problem.

  • It gave me a good north, but like this, in my db I pull the hours by the date, then if the guy does 3 services with different hours he generates me the hour worked of each service... I wanted to add these hours worked, para na minha tabela la na view... Is there any way to do that ? Like I go through a for, it stores the date and add with the others that comes ?

  • 1

    Cara edits your question and tries to exemplify what you really want, so it gets kind of hard to help you.

  • I edited it, see if you can understand what I want to do, once again, thank you!

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.