Sum of Total Positive and Negative Hours

Asked

Viewed 211 times

4

I need to perform the sum of positive and negative hours for a virtual electronic point control. However, I am having difficulties to accomplish the sum, because the hours are not being correctly added up, and when it is added up, the hours of the day are being parameterized and not the total hours.

My code already brings me the hours of each electronic point beat and I can rescue the beat times of each day and print on screen without problems. What I cannot do is add up the hours that have exceeded the working hours of the employees (the logic for calculating excess hours also works perfectly).

Let’s get to the problem. 1- This is the HTML table that prints the values:

ID | Excedentes |
1  |  - 03:00   |
2  |  + 00:14   |
3  |  + 00:20   |
4  |  - 01:24   |
5  |  - 00:02   |
6  |  + 00:01   |
---|------------|

Total Positivo que está trazendo: + 00:01
//O correto seria trazer + 00:35 (com base nestes dados informados)

Total Negativo que está trazendo: - 11:26
//O correto seria trazer - 04:26 (com base nestes dados informados)

It is worth mentioning that the hours can exceed 24 hours, because I need to know the total sum.

2- This is the code that stores the rescued time from the database (I used a global variable to make it easier to rescue on screen in the PHP tag):

/*Acima desse código existe todas as tratativas que funciona corretamente
 para armazenar, resgatar e imprimir os dados na tela, apenas crio uma
variável global para armazenar o valor (pois o mesmo está dentro de um loop,
e cada vez que passa pelo loop, naturalmente o valor muda)*/

        $GLOBALS['negativas'] = 0;
        $GLOBALS['positivas'] = 0;

        if($sinal == "- "){
            $GLOBALS['negativas'] = ($horas.':'.$minutos);
        }
        if($sinal == "+ "){
            $GLOBALS['positivas'] = ($horas.':'.$minutos);
        }

     //Retorna na tela as horas excedidas juntamente com o sinal + ou - em horas 
  /* (este return também já está correto, pois ele é a tabela que demonstrei
        anteriormente).*/
            return '<span style="color:'.$style.'">'.$sinal.$horas.':'.$minutos.'<input hidden value="'.$sinal.$horas.':'.$minutos.'"></span>';

3- Here, is the code I’m trying to accomplish on screen to print the total:

<?php //imprime as horas excedidas do dia
     echo $somatorio->horasExcedidasDia($intervals, $expediente,$registro->getDiaSemana(), $registro->getMarcacoes(), $funcionario->getHorario()->getId());
     $positivas = strtotime($GLOBALS['positivas']);
     $negativas += strtotime($GLOBALS['negativas']);

<td>+ <strong><?php echo date('H:i',$positivas) ?></strong></td>
<td colspan="2">- <strong><?php echo date('H:i', $negativas); ?></strong></td>
?>

4- I made a var_dump (only in the negative hours) on the screen so that you can view the sum that PHP is doing (which by the way is incorrect).

ID | Excedentes | VAR_DUMP |
1  |  - 03:00   | 03:00 ok |
2  |  + 00:14   |     -    |
3  |  + 00:20   |     -    |
4  |  - 01:24   | 08:24 err|
5  |  - 00:02   | 11:26 err|
6  |  + 00:01   |     -    |
---|------------|----------|

NOTE: The values that are in the column SURPLUS, is exactly the values that I am passing to the global.

3 answers

5


What happens is that you are confusing "times" with "durations". To better understand, consider the two sentences below:

  • the movie starts at two o'clock in the afternoon
  • the film lasts two hours

In the first case, "two hours" refers to a timetable: to a specific moment of the day.

In the second case, "two hours" refers to a duration: one amount of time. In this case, it does not say when the film begins or ends (nor whether it was actually shown). It only tells the duration (how long it lasts) without any relation to any specific time.

The problem is that we use the same words (hours, minutes, etc.) for both, but they are different concepts. To make matters worse, even the way of writing can be the same: for example, many chronometers show 02:00 to indicate a duration of two hours.


That said, strtotime serves to deal with dates (specific points of a calendar) and times (specific moments of a day), but does not serve to work with durations.

In this case, you can handle the data manually. One option is to calculate the total minutes, and then convert the final result into hours and minutes:

$tempos = [ '- 03:00', '+ 00:14', '+ 00:20', '- 01:24', '- 00:02', '+ 00:01' ];

$positivos = 0;
$negativos = 0;
foreach ($tempos as $t) {
    $v = explode(' ', $t);
    $campos = explode(':', $v[1]);
    $duracaoMinutos = ($campos[0] * 60) + $campos[1];
    if ($v[0] == '+') {
        $positivos += $duracaoMinutos;
    } elseif ($v[0] == '-') {
        $negativos += $duracaoMinutos;
    }
}

function formatar($duracaoMinutos) {
    $h = floor($duracaoMinutos / 60);
    $m = $duracaoMinutos % 60;
    return sprintf("%02d:%02d", $h, $m);
}

echo formatar($positivos); // 00:35
echo formatar($negativos); // 04:26
  • Thank you very much, I was able to understand perfectly and it was clear the understanding of the code and application.

1

I believe that your sum occurs correctly, but when it comes to showing the result, as you convert to date format, it makes confusion with times greater than 24 hours. Try to do the operations with hours/minutes separately and show as same text

  • Dude, I think it worked. But I had to make some deals due to the minutes (I don’t know why) being over 60 minutes, otherwise it seems to have solved!

0

Although I already have solution to this question, I had a little headache to solve my problem that I calculate balance for a bank of hours, and I would like to share my solution.

In the system, we launch overtime and compensations, recording in the database these records and also updating the balance of the hours bank.

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ATUALIZAR SALDO BANCO HORAS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


//busca o saldo_banco_horas----------------------------------------------------------------------------
$consulta_saldo  = mysql_query("SELECT saldo_banco_horas FROM tb_banco_horas_saldo WHERE cod_funcionario = '$cod_funcionario'")or die("Error1:" .mysql_error());
$resultado_saldo = mysql_fetch_array($consulta_saldo);
$saldo_banco_horas = $resultado_saldo['saldo_banco_horas'];

//variaveis para teste---------
//$tipo_banco_horas = 'C';  //E (hora extra); C (compensacao)
//$saldo_banco_horas = "01:59";
//$qtd_horas = "00:45";

echo "saldo_banco: $saldo_banco_horas<br>";

//verifico o sinal do saldo, se positivo ou negativo
$sinal_saldo = $saldo_banco_horas[0];
echo "sinal_saldo: $sinal_saldo<br>";

echo "tipo_banco_horas: $tipo_banco_horas<br>";
echo "saldo_banco_horas: $saldo_banco_horas<br>";
echo "qtd_horas: $qtd_horas<p>";


//se já houver saldo cadastrado no banco de dados, faço os calculos -------------------------------------------------
if(mysql_num_rows($consulta_saldo)>0){

 //retiro o sinal de negativo, caso o saldo_banco_horas gravado seja negativo
 if($sinal_saldo == "-") $saldo = substr($saldo_banco_horas, 1);
 if($sinal_saldo != "-") $saldo = $saldo_banco_horas;
 echo "saldo  $saldo<p>";

 //transformo o saldo em segundos
 $partes_saldo = explode(':', $saldo);
 $segundos_saldo = $partes_saldo[0] * 3600 + $partes_saldo[1] * 60 + $partes_saldo[2];
 echo "segundos saldo: $segundos_saldo<p>";

 //transformo a qtd_horas(valor que esta sendo passado via formulario)  em segundos
 $partes_horas = explode(':', $qtd_horas);
 $segundos_horas = $partes_horas[0] * 3600 + $partes_horas[1] * 60 + $partes_horas[2];
 echo "segundos horas: $segundos_horas<p>";


 //se o saldo era negativo
 if($sinal_saldo == "-") {

  if($tipo_banco_horas == 'E'){
    $segundos = -$segundos_saldo + $segundos_horas;
  }

  if($tipo_banco_horas == 'C'){
    $segundos = -$segundos_saldo - $segundos_horas;
  }

  echo "segundos: $segundos<p>";

 }


 //se o saldo era positivo
 if($sinal_saldo != "-") {

  if($tipo_banco_horas == 'E'){
   $segundos = $segundos_saldo + $segundos_horas;
  }

  if($tipo_banco_horas == 'C'){
   $segundos = $segundos_saldo - $segundos_horas;
  }

  echo "segundos: $segundos<p>";

 }


 //funcao para converter segundos em horas novamente-----------------------------------------------------------
 function getFullHour($input) {
  $seconds = intval($input); //Converte para inteiro

  $negative = $seconds < 0; //Verifica se é um valor negativo

  if ($negative) {
   $seconds = -$seconds; //Converte o negativo para positivo para poder fazer os calculos
  }

  $hours = floor($seconds / 3600);
  $mins = floor(($seconds - ($hours * 3600)) / 60);
  $secs = floor($seconds % 60);

  $sign = $negative ? '-' : ''; //Adiciona o sinal de negativo se necessário

  return $sign . sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
 }//-----------------------------------------------------------------------------------------------------------

 //echo getFullHour(685), PHP_EOL; //00:11:25
 //echo getFullHour(140801), PHP_EOL; //39:06:41
 //echo getFullHour(-140801), PHP_EOL; //-39:06:41

 $saldo_final = getFullHour($segundos);
 echo "saldo_final: $saldo_final<p>";


} //fecha mysql_num_rows($consulta_saldo)>0)



//se nao tiver saldo cadastrado no banco, saldo recebe qtd_horas informada
if(mysql_num_rows($consulta_saldo)<=0){

 if($tipo_banco_horas == 'E') $saldo_final =  $qtd_horas;
 if($tipo_banco_horas == 'C') $saldo_final =  "-".$qtd_horas;
 echo "saldo_final: $saldo_final<p>";

}

Browser other questions tagged

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