Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Bom dia! Preciso realizar um calculo que me retorne a quantidade de horas que uma maquina ficou parada, em meu banco de dados tenho dois campo data/minutos, que são de data parada e data retorno, os mesmos estão no seguinte formato:
$dataIni = '201704120850' ;
$dataFim = '201704120955';
Até ai consigo fazer o cálculo com a seguinte função:
$dtIni = '201704120850';
$dtFim = '201704120955';
$datatime1 = new DateTime($dtIni);
$datatime2 = new DateTime($dtFim);
$data1 = $datatime1->format('Y-m-d H:i:s');
$data2 = $datatime2->format('Y-m-d H:i:s');
$data1 = strtotime($data1);
$data2 = strtotime($data2);
$nHoras = ($data2 - $data1) / 3600;
$nMinutos = (($data2 - $data1) % 3600) / 60;
$total = sprintf('%02d:%02d', $nHoras , $nMinutos);
echo $total;
O problema agora é que preciso levar em consideração apenas o horário de funcionamento das maquinas que seria das 07:30 até 12:00 e das 13:30 as 17:48, e desconsiderar os sábados, domingos e feriados.Boa tarde a função que retorna as horas úteis desconsiderando finais de semana e feriados eu consegui fazer hoje, o meu problema agora é justamente a questão das horas, pois as maquinas funcionam apenas das 07:30 até 12:00 e das 13:30 as 17:48,
portando as horas contabilizadas fora desses períodos devem ser subtraídas do total. Segue meu código fonte atualizado.
public function horas_paradas(){
//define que não serão utilizado a view para estão requisição
$this->autoRender = $this->layout = false;
$feriado = '20170416';
$inicio1 = '07:30';
$fim1 = '12:00';
$inicio2 = '13:30';
$fim2 = '17:48';
$dtIni = '201704120850';
$dtFim = '201704170851';
$datatime1 = new DateTime($dtIni);
$datatime2 = new DateTime($dtFim);
$data1 = $datatime1->format('Y-m-d H:i:s');
$data2 = $datatime2->format('Y-m-d H:i:s');
$diasUteis = $this->_getDiasUteis($data1, $data2);
$total = $diasUteis * 24;
echo $total; die;
}
function _getDiasUteis($dataIni, $dataFim) {
$dataIni = substr($dataIni,0,10);
$dataFim = substr($dataFim,0,10);
$inicio = strtotime($dataIni);
$fim = strtotime($dataFim);
$ano = date("Y",$inicio);
$feriados = array(
strtotime($ano.'-04-16') => 'Teste', //1492343400 //1492311600
strtotime($ano.'-01-01') => 'Confraternização Universal',
strtotime($ano.'-02-27') => 'Carnaval',
strtotime($ano.'-02-28') => 'Carnaval',
strtotime($ano.'-04-14') => 'Paixão de Cristo',
strtotime($ano.'-04-21') => 'Tiradentes',
strtotime($ano.'-05-01') => 'Dia do Trabalho',
strtotime($ano.'-06-15') => 'Corpus Christi',
strtotime($ano.'-09-07') => 'Independência do Brasil',
strtotime($ano.'-10-12') => 'Nossa Sr.a Aparecida',
strtotime($ano.'-11-02') => 'Finados',
strtotime($ano.'-11-15') => 'Proclamação da República',
strtotime($ano.'-12-25') => 'Natal'
);
if ($inicio > $fim) {
return 0;
} else {
$qtdDias = 0;
$qtdFds = 0;
$qtdFeriados = 0;
while ($inicio <= $fim) {
$qtdDias++;
$dia = date("N", $inicio);
if ($dia > 5) { // 6-Sábado - 7-Domingo
$qtdFds++;
}
if(array_key_exists($inicio, $feriados) && $dia <= 5) {
$qtdFeriados++;
}
$inicio += 86400; // +1 dia
}
$diasUteis = $qtdDias - $qtdFds - $qtdFeriados;
return $diasUteis;
}
}Se entendi o seu problema, você não precisa subtrair os horários invalido, por exemplo:
Se a entrada for **06:20**, você **ajusta** para **07:30**;
Se a saída for **20:00**, você **ajusta** para **17:48**. "De certa forma é uma subtração"
Veja se te atende:
function diaUtil($data, $feriados)
{
/**
Verifica se a data corresponde a um final de semana
*/
if( stristr('Sunday, Saturday', $data->format('l'))) {
return false;
}
/**
verifica se data corresponde a um feriado
*/
if (in_array($data->format('md'), $feriados)) {
return false;
}
return true;
}
function calculaIntevaloDeHorasEmDiasUteis($dataInicio, $dataFim, $feriados) {
$dataInicio = new \DateTime($dataInicio);
if (diaUtil($dataInicio, $feriados)) {
$dataFim = new \DateTime($dataFim);
$horariosValidos = ajustaHorario($dataInicio, $dataFim);
$dataInicio->setTime(substr($horariosValidos[0], 0,2), substr($horariosValidos[0], 2,4) );
$dataFim->setTime(substr($horariosValidos[1], 0,2), substr($horariosValidos[1], 2,4) );
return $dataInicio->diff($dataFim)->format("%H:%I:%S");
}
}
function ajustaHorario($dataInicio, $dataFim)
{
$horarioInicio = $dataInicio->format("Hi");
$horarioFim = $dataFim->format("Hi");
if ($horarioInicio < '0730') {
$horarioInicio = '0730';
}
elseif ($horarioInicio > '1748') {
$horarioInicio = '1748';
}
elseif ($horarioInicio > '1200' and $horarioInicio < '1330') {
$horarioInicio = '1330';
}
if ($horarioFim < '0730') {
$horarioFim = '0730';
}
elseif ($horarioFim > '1748') {
$horarioFim = '1748';
}
elseif ($horarioFim > '1200' and $horarioFim < '1330') {
$horarioFim = '1330';
}
return [$horarioInicio, $horarioFim];
}
$feriados = [
'0101',
'2802',
'1404',
'1604',
'2104',
'0501',
];
echo calculaIntevaloDeHorasEmDiasUteis('201705050830', '201705050850', $feriados);echo calculaIntevaloDeHorasEmDiasUteis('201705051330', '201705051450', $feriados);
echo calculaIntevaloDeHorasEmDiasUteis('201705050630', '201705051250', $feriados);
echo calculaIntevaloDeHorasEmDiasUteis('201705051210', '201705051850', $feriados);
echo calculaIntevaloDeHorasEmDiasUteis('201705050510', '201705050650', $feriados);
echo calculaIntevaloDeHorasEmDiasUteis('201705051910', '201705052050', $feriados);
Bom dia @EdCesar !
Era isso mesmo que eu precisava. Obrigado pela ajuda, ficou muito bom o código.
Estava testando aqui alguns outros períodos e em alguns está retornando a quantidade errada.
Por exemplo:
$dtIni = '201704121159';
$dtFim = '201704121331';
está retornando 01:32, quando deveria ser apenas 2 minutos, pois o restante do tempo ocorreu durante o intervalo. Tentei mexer nas validações da função ajustaHorario o dia inteiro, mas não consegui chegar em uma solução.@hwrry tem varias formas de resolver, veja se essa ideia fica legal. Adicione no final de ajustaHorario(), antes do return
elseif($horarioInicio < '1200' and $horarioFim > '1330'){
$horarioInicio += '0130';
}
Como no final sera feito uma subtração do final com o inicio, eu adiciono o período das 12:00 às 13:30, que corresponde a uma hora e meia, no horário inicial, que servira como debito.
Acredito que com mais essa adição, todos os cenários ficam cobertos.Agora fechou EdCesar! Obrigado.
>
40 minutos atrás, EdCesar disse:
Acredito que com mais essa adição, todos os cenários ficam cobertos.
Ops, na verdade tem mais um caso. Adicione também no final de ajustaHorario(), antes do return
if($horarioInicio < '1200' and $horarioFim > '1200' and $horarioFim <= '1330'){
$horarioFim = '1200';
}
Daria erro nesse cenário:
echo calculaIntevaloDeHorasEmDiasUteis('201704121150', '201704121320', $feriados) . PHP_EOL;
/*
Como os feriados estaduais e municipais variam de região para região, complete o array abaixo
de acordo com o seu caso.
Dica: Para ficar melhor organizado, crie um arquivo feriados.php e depois faça o include
*/
$feriados = [
'0101',
'2802',
'1404',
'1604',
'2104',
echo calculaIntevaloDeHorasEmDiasUteis($dataInicio, $dataFim, $feriados); // 01:05