Próximo/Imediato dia útil com base em uma dta específic
Amigos,
Estava desenvolvendo uma rotina de impressão de segunda via de boleto quando me deparei com uma questão do programa: Cálculo de p´roximo dia útil.
Como não encontrei algo extamente como o que desenvolvi, então resolvi compartilhar com vocês essa simples rotina.
<?php
// Define o formato de saída da data
define('FR_DATA', 'd/m/Y');
// Teste
echo proDiaUtil('06/04/2012'); // Sexta-feira santa; Retorna o dia 09/04/2012 dia útil imediato.
/*
* proDiaUtil()
* Retorna o próximo dia útil em relação a data.
*
* @data -> Variável que recebe a data.
* Formato: DD/MM/AAAA
*/
function proDiaUtil($data)
{
// Separa a data
$dt = explode('/', $data);
$dia = $dt[0];
$mes = $dt[1];
$ano = $dt[2];/*
(1) Pega uma data de referência (variável), compara com o datas definidas pelo sistema (feriados e finais de semana)
e retorna a próxima data um dia útil
(2) As datas do sistema são: [1] sábados; [2] domingos; [3] feriados fixos; [4] feriados veriáveis; [5] dias opcionais (ex: quarta de cinza)
(3) Retorno o próximo/imediato dia útil.
*/
// 1 - verifica se a data referente é um final de semana (sábado ou domingo);
// se sábado acrescenta mais 1 dia e faz nova verificação
// se domingo acrescenta mais 1 dia e faz nova verificação
$fsem = date('D', mktime(0,0,0,$mes,$dia,$ano));
$i = 1;switch($fsem)
{
case 'Sat':
return proDiaUtil(date(FR_DATA, mktime(0,0,0,$mes,$dia+$i,$ano)));
break;
case 'Sun':
return proDiaUtil(date(FR_DATA, mktime(0,0,0,$mes,$dia+$i,$ano)));
break;
default:
// 2 - verifica se a data referente é um feriado
if(in_array($data, Feriados($ano))== true)
{
return proDiaUtil(date(FR_DATA, mktime(0,0,0,$mes,$dia+$i,$ano)));
}
else
{
// Retorna o dia útil
return $data;
}
break;
}
}
/*
* Feriados()
* Gera um array com as datas dos feriados com referência no ano da data pesquisada.
*
* @ano -> Variável que recebe o ano base para o cálculo;
*/
function Feriados($ano)
{
$feriados = array
(
// Armazena feriados fíxos
date(FR_DATA, mktime(0,0,0,'01','01',$ano)), // 01/01 Ano novo
date(FR_DATA, mktime(0,0,0,'04','21',$ano)), // 21/04 Tiradentes
date(FR_DATA, mktime(0,0,0,'05','01',$ano)), // 01/05 Dia do trabalho
date(FR_DATA, mktime(0,0,0,'09','07',$ano)), // 07/09 Independencia
date(FR_DATA, mktime(0,0,0,'10','12',$ano)), // 12/10 Aparecida
date(FR_DATA, mktime(0,0,0,'11','02',$ano)), // 02/11 Finados
date(FR_DATA, mktime(0,0,0,'11','15',$ano)), // 15/11 Proclamação
//date(FR_DATA, mktime(0,0,0,'12','24',$ano)), // 24/12 Véspera de Natal
date(FR_DATA, mktime(0,0,0,'12','25',$ano)), // 25/12 Natal
//date(FR_DATA, mktime(0,0,0,'12','31',$ano)), // 31/12 Véspera de Ano novo
// Armazena feriados variáveis
//flxFeriado($ano, 'pascoa', $r = 1), // Páscoa - Sempre domingo
flxFeriado($ano, 'carn_sab', $r = 1), // Carnaval - Sempre sábado
flxFeriado($ano, 'carn_dom', $r = 1), // Carnaval - Sempre domingo
flxFeriado($ano, 'carn_seg', $r = 1), // Carnaval - Segunda
flxFeriado($ano, 'carn_ter', $r = 1), // Carnaval - Terça
//strtoupper(flxFeriado($ano, 'carn_qua', $r = 1)), // Carnaval - Quarta de cinza
flxFeriado($ano, 'sant_sex', $r = 1), // Sexta Santa
flxFeriado($ano, 'corp_chr', $r = 1) // Corpus Christi
);
return $feriados;
}
/*
* flxFeriado()
* Calcula os dias de feriados variáveis. Com base na páscoa.
*
* @ano -> Variável que recebe o ano base para o cálculo;
* @tipo -> Tipo de dados
* [carn_sab]: Sábado de carnaval;
* [carn_dom]: Domingo de carnaval;
* [carn_seg]: Segunda-feira de carnaval;
* [carn_ter]: Terça-feira de carnaval;
* [carn_qua]: Quarta-feira de carnaval;
* [sant_sex]: Sexta-feira santa;
* [corp_chr]: Corpus Christi;*/
function flxFeriado($ano, $tipo = NULL)
{
$a=explode("/", calPascoa($ano));
switch($tipo)
{
case 'carn_sab': $d = $a[0]-50; break;
case 'carn_dom': $d = $a[0]-49; break;
case 'carn_seg': $d = $a[0]-48; break;
case 'carn_ter': $d = $a[0]-47; break;
case 'carn_qua': $d = $a[0]-46; break;
case 'sant_sex': $d = $a[0]-2; break;
case 'corp_chr': $d = $a[0]+60; break;
case NULL:
case 'pascoa': $d = $a[0]; break;
}
return date(FR_DATA, mktime(0,0,0,$a[1],$d,$a[2])); break;
}
/*
* calPascoa()
* Calcula o domingo da pascoa. Base para todos os feriádos móveis.
*
* @ano -> Variável que recebe o ano base para o cálculo ;
*/
function calPascoa($ano)
{
$A = ($ano % 19);
$B = (int)($ano / 100);
$C = ($ano % 100);
$D = (int)($B / 4);
$E = ($B % 4);
$F = (int)(($B + 8) / 25);
$G = (int)(($B - $F + 1) / 3);
$H = ((19 * $A + $B - $D - $G + 15) % 30);
$I = (int)($C / 4);
$K = ($C % 4);
$L = ((32 + 2 * $E + 2 * $I - $H - $K) % 7);
$M = (int)(($A + 11 * $H + 22 * $L) / 451);
$P = (int)(($H + $L - 7 * $M + 114) / 31);
$Q = (($H + $L - 7 * $M + 114) % 31) + 1;
return date('d/m/Y', mktime(0,0,0,$P,$Q,$ano));
}
?>
Podemo opinar a vontade sobre o código, otimizá-lo e propor melhorias.
Como fiz esse código para cálcula o próximo dia útil, então serve também para jerar multas e mora diária em caso de atraso, para isso, basta calcular a diferença entre datas, que eu resolvi assim:
// Teste
$c = cData(proDiaUtil('06/04/2012'), proDiaUtil(date('d/m/Y')));
// Lógica (bem simples)
// Se $c menor ou igual a zero, siginifica que o boleto está em dia, caso contrário está atrasado $c dias
if($c <= 0)
{
echo "em dia.";
}else
{
echo "O boleto está atrasado ". $c ." dia(s)."
}
/*
*Calculando diferença entre datas
*@dt_boleto -> Variável que recebe a data de vencimento do banco de dados DD/MM/AAAA
*@dt_agora -> Variável que recebe a data de agora DD/MM/AAAA
*/
function cData($dt_boleto, $dt_agora){
$dt1 = explode('/', $dt_boleto);
$d1 = $dt1[0];
$m1 = $dt1[1];
$a1 = $dt1[2];
$dt2 = explode('/', $dt_agora);
$d2 = $dt2[0];
$m2 = $dt2[1];
$a2 = $dt2[2];
$data1 = $d1 .'/'. $m1 .'/'. $a1;
$data2 = $d2 .'/'. $m2 .'/'. $a2;
//cálculo timestamp das duas datas
$timestamp1 = mktime(0,0,0,$m1,$d1,$a1);
$timestamp2 = mktime(0,0,0,$m2,$d2,$a2);
//diminuo uma data a outra
$segundos_diferenca = $timestamp2 - $timestamp1;
//converto segundos em dias
$dias_diferenca = $segundos_diferenca / (60 * 60 * 24);
//tira decimais e arredonda
$dias_diferenca = floor($dias_diferenca);
return $dias_diferenca;
}
Obrigado por me ajudarem tanto.
Discussão (2)
Carregando comentários...