Jump to content


Photo

Calculo De DiferenÇa De Horas


  • Faça o login para participar
13 replies to this topic

#1 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 14/11/2009, 15:16

Pessoal, estou com um problema nesse codigo, se as variáveis $tdeb e $tcred apresentarem valores inferiores a 24:00 o resultado fica perfeito, porém as vezes os resultados são superiores a 24:00 e no calculo da diferença entre elas gera erro, por exemplo se o resultado for 36:00 em $tdeb e 06:00 em $tcred o resultado de $tohor é 06:00 e não 30:00 como deveria ser, ou seja quando passa de 24:00 ele zera e conta novamente.
Como poderia resolver essa questão? Alguém pode me dar uma sugestão?


$sql = mysql_query("SELECT SEC_TO_TIME( SUM(TIME_TO_SEC( jorndif ) ) ) AS total_horas FROM ponto$comp USE INDEX (siape) where oco in('00172','55555') and siape = '$mat'");
$tdeb = mysql_result($sql,0,"total_horas");
$sq = mysql_query("SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( jorndif ) ) ) AS total_horas FROM ponto$comp USE INDEX (siape) where oco = '33333' and siape = '$mat'");
$tcre = mysql_result($sq,0,"total_horas");
$hodeb = explode(":", $tdeb);
$hocre = explode(":", $tcre);


if($tdeb > $tcre && !empty($tcre))
{
$thor = mktime ($hodeb[0] - $hocre[0], $hodeb[1] - $hocre[1], 0, 0 );
$tohor = date("H:i", $thor);

#2 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 15/11/2009, 00:25

Isso que você fez aí é meio estranho, por causa desses retornos...

O indicado é pegar primeiro a diferença das horas, isso pode ser feito direto na query. Com uma única query você pode ter o retorno das horas.

Se você explicar sua tabela, eu posso te auxiliar.

(ok2)
att,
Muller Dias
ex-administrador Fórum WMO

#3 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 15/11/2009, 08:50

'' sem.Ponto obrigado por responder, vamos lá , a tabela possui um campo DIA onde são registrados os horários praticados nesse dia por um funcionário, um campo SIAPE que registra quem é o funcionario, um campo JORNDIF que registra o resultado do dia que pode ser no máximo de 08:00 que é a jornada de trabalho do funcionario, temos ainda um campo OCO que registra a ocorrência do dia, se positiva recebe o codigo 33333 se negativa recebe o codigo 55555 ou 00172, existem outros campos mas esses são os que precisamos para fazer o cálculo, então devo somar os codigos 33333 e comparar com a soma dos 55555 e 00172 para ver quem é maior e fazer o calculo da diferença pois ora os creditos são maiores ora os débitos são maiores, por isso fiz um select para debitos e outro para créditos, mas sua idéia é boa como é que poderia fazer o select já calculando a diferença?

#4 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 15/11/2009, 13:51

Não era bem o que eu estava pensando que fosse... :ponder:

Bom, você pode fazer assim:

// Essa query me retorna 3 linhas, cada linha contém a soma dos segundos de cada ocorrência do usuário
$sql = mysql_query("SELECT SUM(TIME_TO_SEC(JORNDIF)) as segundos, OCO FROM sua_tabela_aqui
WHERE SIAPE='".$mat."'
GROUP BY OCO");

// Nas variáveis declaradas abaixo, em $tempo->positivo vai entrar os segundos da OCO 33333 e em $tempo->negativo vai entrar a soma da OCO 55555 e OCO 00172
$tempo->positivo = 0;
$tempo->negativo = 0;

// Faço o loop nas 3 linhas retornadas na query
while ($row = mysql_fetch_object($sql)) {
	 // se OCO é 33333, jogo os segundos em $tempo->positivo
	 if ($row->OCO == 33333) {
		  $tempo->positivo = $row->segundos;
	 }
	 // senão vou somando as outras OCO em $tempo->negativo
	 else {
		  $tempo->negativo += $row->segundos;
	 }
}

// Verifico qual variável tem o maior valor e faço o cálculo. O resultado é em segundos.
$resultado = ($tempo->positivo > $tempo->negativo) ? $tempo->positivo - $tempo->negativo : $tempo->negativo - $tempo->positivo;

Acho que está tudo certo, qualquer dúvida, poste. ;)

(ok2)
att,
Muller Dias
ex-administrador Fórum WMO

#5 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 15/11/2009, 20:07

Muito obrigado pela dica, ficou bom o codigo mas ainda tenho um problema no else não posso somar todos os codigos restantes preciso somar apenas os grupos indicados 00172 e 55555, então troquei para elseif abaixo, mas não está somando.
Me desculpe mas ainda tenho muito a aprender.

elseif($row->OCO == 00172 || $row->OCO == 55555)
{
$tempo->negativo += $row->segundos;
}


Não era bem o que eu estava pensando que fosse... :ponder:

Bom, você pode fazer assim:

// Essa query me retorna 3 linhas, cada linha contém a soma dos segundos de cada ocorrência do usuário
$sql = mysql_query("SELECT SUM(TIME_TO_SEC(JORNDIF)) as segundos, OCO FROM sua_tabela_aqui
WHERE SIAPE='".$mat."'
GROUP BY OCO");

// Nas variáveis declaradas abaixo, em $tempo->positivo vai entrar os segundos da OCO 33333 e em $tempo->negativo vai entrar a soma da OCO 55555 e OCO 00172
$tempo->positivo = 0;
$tempo->negativo = 0;

// Faço o loop nas 3 linhas retornadas na query
while ($row = mysql_fetch_object($sql)) {
	 // se OCO é 33333, jogo os segundos em $tempo->positivo
	 if ($row->OCO == 33333) {
		  $tempo->positivo = $row->segundos;
	 }
	 // senão vou somando as outras OCO em $tempo->negativo
	 else {
		  $tempo->negativo += $row->segundos;
	 }
}

// Verifico qual variável tem o maior valor e faço o cálculo. O resultado é em segundos.
$resultado = ($tempo->positivo > $tempo->negativo) ? $tempo->positivo - $tempo->negativo : $tempo->negativo - $tempo->positivo;

Acho que está tudo certo, qualquer dúvida, poste. ;)

(ok2)



#6 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 15/11/2009, 22:02

Você fez quase certo... ^_^

O correto é else if, você colocou elseif junto. ;)

else if ($row->OCO == 00172 || $row->OCO == 55555)
{
	 $tempo->negativo += $row->segundos;
}

Mas, você nem precisa disso... ^_^

Você pode simplesmente colocar uma codição na query para pegar apenas os códigos que você quer. Faça isso:

$sql = mysql_query("SELECT SUM(TIME_TO_SEC(JORNDIF)) as segundos, OCO FROM sua_tabela_aqui
WHERE SIAPE='".$mat."' AND OCO IN ('33333','00172','55555')
GROUP BY OCO");

Assim não tem problema usar o else, pois na consulta não vai retornar códigos que você não precisa. ;)

(ok2)
att,
Muller Dias
ex-administrador Fórum WMO

#7 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 16/11/2009, 15:00

Entendi, ficou bom mesmo vou testar.

Entendi, ficou bom mesmo vou testar.

'' sem.Ponto testei e deu erro, ele soma tudo, coloquei no tabela 02:00 para o codigo 00172 e tres codigos 33333 com 08:00 cada o que daria 24 de credito contra 02 de debito o resultado está gerando 26:00 e não 24:00, o que poderia ser?

#8 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 16/11/2009, 16:39

Bom, o código está todo certo... :ponder:

Dê um print_r($tempo); e posta aqui.

O campo JORNDIF é do tipo TIME né?

Você fez alguma alteração, como por exemplo converter os segundos para horas? Pois o retorno é dado em segundos, você disse que está gerando 26:00, provavelmente você fez alguma alteração aí...

Qualquer coisa eu vou te pedir para rodar umas querys direto no phpmyadmin para descobrir se está pegando os registros corretamente.

(ok2)
att,
Muller Dias
ex-administrador Fórum WMO

#9 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 16/11/2009, 18:03

O print_r deu o seguinte:

stdClass Object ( [positivo] => 0 [negativo] => 93600 )

O campo jornidf é varchar

Sim alterei acrescentei o seguinte

$resultado = $resultado/3600;
echo $resultado;

#10 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 16/11/2009, 18:06

O campo jornidf tem que ser do tipo TIME, no formato 00:00:00.

Pelo visto não está entrando na condição $row->OCO == 33333... :ponder:

Faça o seguinte teste:

$sql = mysql_query("SELECT SUM(TIME_TO_SEC(JORNDIF)) as segundos, OCO FROM sua_tabela_aqui
WHERE SIAPE='".$mat."' AND OCO IN ('33333','00172','55555')
GROUP BY OCO");

while ($row = mysql_fetch_object($sql)) {
	 $rows[] = $row;
}

print_r($rows);

E também:

$sql = mysql_query("SELECT JORNDIF, OCO FROM sua_tabela_aqui
WHERE SIAPE='".$mat."' AND OCO IN ('33333','00172','55555')");

while ($row = mysql_fetch_object($sql)) {
	 $rows[] = $row;
}

print_r($rows);

Não se esqueça de mudar a tabela nas querys acima. ;)
att,
Muller Dias
ex-administrador Fórum WMO

#11 Spark Eyes

Spark Eyes

    Novato no fórum

  • Usuários
  • 9 posts
  • Sexo:Não informado

Posted 16/11/2009, 18:46

assim, qual é o formato de horas que você usa?

eu criei um script em php que pode te ajudar muito!

so gostaria de saber o formato que a data fica no banco de dados!

#12 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 16/11/2009, 20:40

Spark, toda ajuda é bem vinda, o campo dia tem o formato date.
Sem Ponto. Vou fazer o teste recomendado.

Sem.Ponto, primeiro teste: Tá pegando certo.
Array ( [0] => stdClass Object ( [segundos] => 7200 [oco] => 00172 ) [1] => stdClass Object ( [segundos] => 86400 [oco] => 33333 ) )

Segundo teste:
Array ( [0] => stdClass Object ( [segundos] => 7200 [oco] => 00172 ) [1] => stdClass Object ( [segundos] => 86400 [oco] => 33333 ) )

echo na $resultado

93600

descobri ele não entrava na condição $row->OCO == 33333 porque estava com zeros 0C0 e é com OCO, o resultado deu certo mesmo com varchar não cheguei nem a mudar, pois antes já dava certo dessa forma, vou testa a mudança para ver o que ocorre.
Indago mas uma questão, como o resultado está em minutos pode me ajudar na conversão para exibição em horas:minutos.

#13 '' sem.Ponto

'' sem.Ponto

    Super Veterano

  • Ex-Admins
  • 2098 posts
  • Sexo:Masculino
  • Localidade:Belo Horizonte

Posted 16/11/2009, 23:36

$segundos = ($tempo->positivo > $tempo->negativo) ? $tempo->positivo - $tempo->negativo : $tempo->negativo - $tempo->positivo;

$horas = floor($segundos / 3600);
$segundos -= $horas * 3600;
$minutos = floor($segundos / 60);
$segundos -= $minutos * 60;

echo sprintf("%02s:%02s:%02s", $horas, $minutos, $segundos);

o resultado deu certo mesmo com varchar não cheguei nem a mudar

Só porque deu certo não quer dizer que é o correto. Se você quer registrar tempo, registre num campo TIME, vai evitar problemas. O VARCHAR aceita qualquer coisa, o TIME valida antes.

O seu campo VARCHAR aceita cadastrar "creme de banana", tempos inválidos como 02:88:99 e qualquer outra coisa que deixaria seu sistema louco. O TIME iria conveter qualquer dado inválido para 00:00:00, isso te dá segurança. ;)

(ok2)
att,
Muller Dias
ex-administrador Fórum WMO

#14 carlosins

carlosins

    Novato no fórum

  • Usuários
  • 19 posts
  • Sexo:Não informado

Posted 18/11/2009, 18:52

sem.Ponto Valeu pela grande ajuda, ficou bom mesmo agora tá rodando legal, acrescentei no final a definição de codigo, quanto a tabela vou mudar para time, melhor garantir.

if($tempo->positivo != $tempo->negativo)
{
$cod = ($tempo->positivo > $tempo->negativo) ? "33333" : "00172";
}
else
{
$cod = "00000";
}




1 user(s) are reading this topic

0 membro(s), 1 visitante(s) e 0 membros anônimo(s)

IPB Skin By Virteq