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>
[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!
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>