Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

D2th3

Próximo/Imediato dia útil com base em uma dta específic

Recommended Posts

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites
<?php

// define a data
$current_date = new DateTime( '2012-04-20' );
//$current_date->setTimezone( new DateTimeZone( 'America/Sao_Paulo' ) );

// se for sexta, sábado ou domingo
if( $current_date->format( 'N' ) >= 5 )
{
   $current_date->add( new DateInterval( sprintf( 'P%sD', ( 8 - $current_date->format( 'N' ) ) ) ) );
}
else
{
   $current_date->add( new DateInterval( 'P1D' ) );
}

echo $current_date->format( 'Y-m-d' ); // 2012-04-23 -> próximo dia útil

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.