D2th3 3 Denunciar post Postado Abril 15, 2012 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
Kakashi_Hatake 267 Denunciar post Postado Abril 17, 2012 <?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
D2th3 3 Denunciar post Postado Abril 17, 2012 Nesse caso é PHP 5.2 ou superior e não tem comparação usando feriados. Abraços Compartilhar este post Link para o post Compartilhar em outros sites