Somar dias úteis em data - PHP

Publicado por Ricardo Herrero em 02/12/2010

[ Hits: 16.277 ]

 


Somar dias úteis em data - PHP



Olá amigos.

Vamos fazer um novo exercício com datas, agora somando dias úteis em uma determinada data.

Vou utilizar as mesmas bibliotecas que usamos para a dica anterior: Cálculo de dias úteis entre duas datas em PHP

Bem, vamos direto aos códigos. Neste exemplo vamos criar algumas funções que vão facilitar nosso trabalho.

Descritivo das funções:

<?
//FORMATA COMO TIMESTAMP
function dataToTimestamp($data){
   $ano = substr($data, 6,4);
   $mes = substr($data, 3,2);
   $dia = substr($data, 0,2);
return mktime(0, 0, 0, $mes, $dia, $ano);  
}
?>

Esta função irá transformar a data que iremos utilizar, conforme padrão mktime.

<? //SOMA 01 DIA
function Soma1dia($data){
   $ano = substr($data, 6,4);
   $mes = substr($data, 3,2);
   $dia = substr($data, 0,2);
return date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
}
?>

Esta função efetua a soma de um dia para uma data qualquer.

<?
//LISTA DE FERIADOS NO ANO
function Feriados($ano,$posicao){
   $dia = 86400;
   $datas = array();
   $datas['pascoa'] = easter_date($ano);
   $datas['sexta_santa'] = $datas['pascoa'] - (2 * $dia);
   $datas['carnaval'] = $datas['pascoa'] - (47 * $dia);
   $datas['corpus_cristi'] = $datas['pascoa'] + (60 * $dia);
   $feriados = array (
      '01/01',
      '02/02', // Navegantes
      date('d/m',$datas['carnaval']),
      date('d/m',$datas['sexta_santa']),
      date('d/m',$datas['pascoa']),
      '21/04',
      '01/05',
      date('d/m',$datas['corpus_cristi']),
      '20/09', // Revolução Farroupilha \m/
      '12/10',
      '02/11',
      '15/11',
      '25/12',
   );
        
return $feriados[$posicao]."/".$ano;
}
?>

Vamos registrar todos os possíveis feriados dentro deste array.

Vocês podem perceber que temos datas de feriados fixos, por exemplo, o natal que é sempre no dia 25 de dezembro e também temos feriados como a páscoa, que precisamos fazer um cálculo para descobrirmos o dia certo do feriado.

Com estas 03 funções acima conseguiremos efetuar a nossa soma de dias úteis.

Segue abaixo a função que fará esta soma:

<?
function SomaDiasUteis($xDataInicial,$xSomarDias){
   for($ii=1; $ii<=$xSomarDias; $ii++){
      
      $xDataInicial=Soma1dia($xDataInicial); //SOMA DIA NORMAL
      
      //VERIFICANDO SE EH DIA DE TRABALHO
      if(date("w", dataToTimestamp($xDataInicial))=="0"){
         //SE DIA FOR DOMINGO OU FERIADO, SOMA +1
         $xDataInicial=Soma1dia($xDataInicial);
        
      }else if(date("w", dataToTimestamp($xDataInicial))=="6"){
         //SE DIA FOR SABADO, SOMA +2
         $xDataInicial=Soma1dia($xDataInicial);
         $xDataInicial=Soma1dia($xDataInicial);
        
      }else{
         //senaum vemos se este dia eh FERIADO
         for($i=0; $i<=12; $i++){
            if($xDataInicial==Feriados(date("Y"),$i)){
               $xDataInicial=Soma1dia($xDataInicial);
            }
         }
      }
   }
return $xDataInicial;
}
?>

Iremos fazer uma verificação dia-a-dia para saber se o dia é útil.

Através da função PHP date, utilizamos o parâmetro w que irá retornar o valor 6 para sábado ou 0 para domingo. Caso esta informação seja falsa, conferimos se a data não é um feriado.

Para efetuarmos a chamada da função que realiza a soma, basta executar a função SomaDiasUteis(a,b), conforme exemplo abaixo.

Desejamos somar 02 dias úteis a partir da data de hoje:

<?= SomaDiasUteis(date("d/m/Y"),5)?>

Galera, é isso. Espero ter ajudado com este código.

Fico no aguardo dos comentários e sugestões para os próximos.

Para visualizar este código funcionando, use o link:
Em breve estarei publicando uma biblioteca que utilizo para efetuar upload de imagem.

Ricardo Herrero
Desenvolvedor web PHP

Abaixo segue o código completo.

Data-SomaDiasUteis.PHP:

<?
//CALCULANDO DIAS NORMAIS
      //LISTA DE FERIADOS NO ANO
      function Feriados($ano,$posicao){
         $dia = 86400;
         $datas = array();
         $datas['pascoa'] = easter_date($ano);
         $datas['sexta_santa'] = $datas['pascoa'] - (2 * $dia);
         $datas['carnaval'] = $datas['pascoa'] - (47 * $dia);
         $datas['corpus_cristi'] = $datas['pascoa'] + (60 * $dia);
         $feriados = array (
            '01/01',
            '02/02', // Navegantes
            date('d/m',$datas['carnaval']),
            date('d/m',$datas['sexta_santa']),
            date('d/m',$datas['pascoa']),
            '21/04',
            '01/05',
            date('d/m',$datas['corpus_cristi']),
            '20/09', // Revolução Farroupilha \m/
            '12/10',
            '02/11',
            '15/11',
            '25/12',
         );
        
      return $feriados[$posicao]."/".$ano;
      }      

      //FORMATA COMO TIMESTAMP
      function dataToTimestamp($data){
         $ano = substr($data, 6,4);
         $mes = substr($data, 3,2);
         $dia = substr($data, 0,2);
      return mktime(0, 0, 0, $mes, $dia, $ano);  
      }

      //SOMA 01 DIA
      function Soma1dia($data){
         $ano = substr($data, 6,4);
         $mes = substr($data, 3,2);
         $dia = substr($data, 0,2);
      return   date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
      }
      
      function SomaDiasUteis($xDataInicial,$xSomarDias){
         for($ii=1; $ii<=$xSomarDias; $ii++){
            
            $xDataInicial=Soma1dia($xDataInicial); //SOMA DIA NORMAL
            
            //VERIFICANDO SE EH DIA DE TRABALHO
            if(date("w", dataToTimestamp($xDataInicial))=="0"){
               //SE DIA FOR DOMINGO OU FERIADO, SOMA +1
               $xDataInicial=Soma1dia($xDataInicial);
              
            }else if(date("w", dataToTimestamp($xDataInicial))=="6"){
               //SE DIA FOR SABADO, SOMA +2
               $xDataInicial=Soma1dia($xDataInicial);
               $xDataInicial=Soma1dia($xDataInicial);
              
            }else{
               //senaum vemos se este dia eh FERIADO
               for($i=0; $i<=12; $i++){
                  if($xDataInicial==Feriados(date("Y"),$i)){
                     $xDataInicial=Soma1dia($xDataInicial);
                  }
               }
            }
         }
      return $xDataInicial;
      }
?>  
<HTML>      
<?
$DataInicial = "04/08/2010";
$QtdDia = 8;
$diasSomados = SomaDiasUteis($DataInicial,$QtdDia);
?>
  
   <BODY>
      <br />
      Somar <?=$QtdDia?> dia(s) de <?=$DataInicial?> = Resultado: <?=$diasSomados?>   ?>
      
   </BODY>
</HTML>

Outras dicas deste autor

Calculo de dias úteis entre duas datas em PHP

Leitura recomendada

Comando find - Expressões pouco conhecidas

Exportando suas contas e mensagens do Thunderbird do Windows para o Linux

O que é a certificação LPIC-1

Corrigindo erro "VM is inaccessible" do VirtualBox

Coisas para fazer após instalar Fedora 16

  

Comentários
[1] Comentário enviado por engalexsandro em 24/01/2013 - 17:34h

Prezado Ricardo. Este Script salvou minha vida... valew d+......... Porém ao testar algumas datas, percebi que este script possui uma falha: não calcula se o feriado cair na Segunda, veja o exemplo: Neste ano (2013) o Carnaval é na 12/02 e 11/02 para mim também não é dia útil, cadastrei essa dara no array feriados, mas como o dia 09/02/2013 cai no sábado, o script soma mais 2 (11/02/2013) e não testa se é feriado e considera dia 11/02 como útil. Fiz a seguinte modificação:

function SomaDiasUteis($xDataInicial,$xSomarDias){
for($ii=1; $ii<=$xSomarDias; $ii++){

$xDataInicial=$this->Soma1dia($xDataInicial); //SOMA DIA NORMAL

//VERIFICANDO SE EH DIA DE TRABALHO
if(date("w", $this->dataToTimestamp($xDataInicial))=="0"){
//SE DIA FOR DOMINGO OU FERIADO, SOMA +1
$xDataInicial=$this->Soma1dia($xDataInicial);

}else if(date("w", $this->dataToTimestamp($xDataInicial))=="6"){
//SE DIA FOR SABADO, SOMA +2
$xDataInicial=$this->Soma1dia($xDataInicial);
$xDataInicial=$this->Soma1dia($xDataInicial);

}
//Este dia eh FERIADO
for($i=0; $i<=13; $i++){
var_dump($xDataInicial,$xDataInicial==$this->Feriados(date("Y"),$i));
echo "<br />";

if($xDataInicial==$this->Feriados(date("Y"),$i)){
$xDataInicial=$this->Soma1dia($xDataInicial);
}
}
}
return $xDataInicial;
}

Abraços.

[2] Comentário enviado por alanjr em 08/06/2015 - 17:11h

Olá Ricardo, só da uma verificada na função SomaDiasUteis, eu inverti a sua lógica.

Primeiro verifiquei se o dia é feriado, aí depois verifico se é sabado ou domingo, estava dando erros em algumas datas, depois que fiz isso começou a funcionar corretamente, abaixo a mudança que fiz.

function SomaDiasUteis($xDataInicial,$xSomarDias){
for($ii=1; $ii<=$xSomarDias; $ii++){
$xDataInicial=Soma1dia($xDataInicial);
for($i=0; $i<13; $i++){
var_dump($xDataInicial,$xDataInicial==Feriados(date("Y"),$i));
echo "<br />";

if($xDataInicial==Feriados(date("Y"),$i)){
$xDataInicial=Soma1dia($xDataInicial);
}else{
//VERIFICANDO SE EH DIA DE TRABALHO
if(date("w",dataToTimestamp($xDataInicial))=="0"){
//SE DIA FOR DOMINGO OU FERIADO, SOMA +1
$xDataInicial=Soma1dia($xDataInicial);

}else if(date("w", dataToTimestamp($xDataInicial))=="6"){
//SE DIA FOR SABADO, SOMA +2
$xDataInicial=Soma1dia($xDataInicial);
$xDataInicial=Soma1dia($xDataInicial);
}
}
}
}
return $xDataInicial;
}

Até mais!

[3] Comentário enviado por GCONTABIL em 08/02/2016 - 02:15h

Como ficaria a função para se a data final fosse o sábado, domingo ou feriado pulasse para o primeiro dia útil?

Alguém pode ajudar.

[4] Comentário enviado por GCONTABIL em 13/03/2016 - 19:47h


[2] Comentário enviado por alanjr em 08/06/2015 - 17:11h

Olá Ricardo, só da uma verificada na função SomaDiasUteis, eu inverti a sua lógica.

Primeiro verifiquei se o dia é feriado, aí depois verifico se é sabado ou domingo, estava dando erros em algumas datas, depois que fiz isso começou a funcionar corretamente, abaixo a mudança que fiz.

function SomaDiasUteis($xDataInicial,$xSomarDias){
for($ii=1; $ii&lt;=$xSomarDias; $ii++){
$xDataInicial=Soma1dia($xDataInicial);
for($i=0; $i&lt;13; $i++){
var_dump($xDataInicial,$xDataInicial==Feriados(date("Y"),$i));
echo "&lt;br /&gt;";

if($xDataInicial==Feriados(date("Y"),$i)){
$xDataInicial=Soma1dia($xDataInicial);
}else{
//VERIFICANDO SE EH DIA DE TRABALHO
if(date("w",dataToTimestamp($xDataInicial))=="0"){
//SE DIA FOR DOMINGO OU FERIADO, SOMA +1
$xDataInicial=Soma1dia($xDataInicial);

}else if(date("w", dataToTimestamp($xDataInicial))=="6"){
//SE DIA FOR SABADO, SOMA +2
$xDataInicial=Soma1dia($xDataInicial);
$xDataInicial=Soma1dia($xDataInicial);
}
}
}
}
return $xDataInicial;
}

Até mais!


Esta função não funciona quanto acrescentamos mais feriados, veja a baixo o código após acrescentar os recesso dia 01 a 06/01. A função não calcula correto? Alguém pode ajudar:

<?
//CALCULANDO DIAS NORMAIS
//LISTA DE FERIADOS NO ANO
function Feriados($ano,$posicao){
$dia = 86400;
$datas = array();
$datas['pascoa'] = easter_date($ano);
$datas['sexta_santa'] = $datas['pascoa'] - (2 * $dia);
$datas['carnaval'] = $datas['pascoa'] - (47 * $dia);
$datas['corpus_cristi'] = $datas['pascoa'] + (60 * $dia);
$feriados = array (

'01/01', //Recesso 20/12 a 06/01
'02/01',
'03/01',
'04/01',
'05/01',
'06/01',
'02/02', // Navegantes
date('d/m',$datas['carnaval']),
date('d/m',$datas['sexta_santa']),
date('d/m',$datas['pascoa']),
'21/04',
'01/05',
'20/06',
'24/06',
date('d/m',$datas['corpus_cristi']),
'20/09', // Revolução Farroupilha \m/
'12/10',
'02/11',
'15/11',
'25/12',

);

return $feriados[$posicao]."/".$ano;
}

//FORMATA COMO TIMESTAMP
function dataToTimestamp($data){
$ano = substr($data, 6,4);
$mes = substr($data, 3,2);
$dia = substr($data, 0,2);
return mktime(0, 0, 0, $mes, $dia, $ano);
}

//SOMA 01 DIA
function Soma1dia($data){
$ano = substr($data, 6,4);
$mes = substr($data, 3,2);
$dia = substr($data, 0,2);
return date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
}

function SomaDiasUteis($xDataInicial,$xSomarDias){
for($ii=1; $ii<=$xSomarDias; $ii++){
$xDataInicial=Soma1dia($xDataInicial);
for($i=0; $i<13; $i++){
var_dump($xDataInicial,$xDataInicial==Feriados(date("Y"),$i));
echo "<br />";

if($xDataInicial==Feriados(date("Y"),$i)){
$xDataInicial=Soma1dia($xDataInicial);
}else{
//VERIFICANDO SE EH DIA DE TRABALHO
if(date("w",dataToTimestamp($xDataInicial))=="0"){
//SE DIA FOR DOMINGO OU FERIADO, SOMA +1
$xDataInicial=Soma1dia($xDataInicial);

}else if(date("w", dataToTimestamp($xDataInicial))=="6"){
//SE DIA FOR SABADO, SOMA +2
$xDataInicial=Soma1dia($xDataInicial);
$xDataInicial=Soma1dia($xDataInicial);
}
}
}
}
return $xDataInicial;
}


?>
<HTML>
<?
$DataInicial = "31/12/2016";
$QtdDia = 1;
$diasSomados = SomaDiasUteis($DataInicial,$QtdDia);

?>

<BODY>
<br />
Somar <?=$QtdDia?> dia(s) Uteis a data inicial <?=$DataInicial?> = Resultado: <?=$diasSomados?>


</BODY>
</HTML>



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts