Olá!
Hoje eu vou publicar funções muito úteis no dia-a-dia: Somar datas considerando dias úteis.
Obs.: Serão considerados dias não úteis apenas os sábados, domingos e feriados nacionais.
Os feriados nacionais são em sua maioria fixos (ex.: 01/05, 07/09, 02/11) e existem alguns feriados “móveis” (ex.: carnaval, páscoa, corpus christi) que são baseados no feriado da páscoa.
Existe uma função nativa do php para retornar a data da páscoa do ano informado (easter_date) que ajuda muito na hora de descobrir os feriados nacionais, mas se você não tiver essa função disponível no seu servidor, então existe uma outra opção. Trata-se de um algorítmo criado em 532 D.C. para descobrir a data da páscoa do ano informado que está postado abaixo:
<!--?php /** * @param string|int $Year * Displays <a href="http://br.php.net/easter_date" _mce_href="http://br.php.net/easter_date"-->php.net * @link http://br.php.net/easter_date */ function retornarPascoa($Year) { /* G is the Golden Number-1 H is 23-Epact (modulo 30) I is the number of days from 21 March to the Paschal full moon J is the weekday for the Paschal full moon (0=Sunday, 1=Monday, etc.) L is the number of days from 21 March to the Sunday on or before the Paschal full moon (a number between -6 and 28) */ $G = $Year % 19; $C = (int)($Year / 100); $H = (int)($C - (int)($C / 4) - (int)((8*$C+13) / 25) + 19*$G + 15) % 30; $I = (int)$H - (int)($H / 28)*(1 - (int)($H / 28)*(int)(29 / ($H + 1))*((int)(21 - $G) / 11)); $J = ($Year + (int)($Year/4) + $I + 2 - $C + (int)($C/4)) % 7; $L = $I - $J; $m = 3 + (int)(($L + 40) / 44); $d = $L + 28 - 31 * ((int)($m / 4)); $y = $Year; $E = mktime(0,0,0, $m, $d, $y); return $E; } ?>
Sabendo que dia é a páscoa, tudo fica mais fácil. Basta descobrir os outros feriados conforme abaixo:
<!--?php /** * @author Rodrigo Régis Palmeira <regisbsb@gmail.com--> * @param string $ano - ano em que se quer calcular os feriados * @return array com feriados nacionais do ano informado do ano (fixo e moveis) */ function retornarFeriados($ano) { $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 ( 'Ano Novo' => '01/01/'.date('Y'), 'Carnaval' => date('d/m/Y',$datas['carnaval']), 'Sexta-Feira Santa' => date('d/m/Y',$datas['sexta_santa']), 'Páscoa' => date('d/m/Y',$datas['pascoa']), 'Tiradentes' => '21/04/'.date('Y'), 'Dia do Trabalhador' => '01/05/'.date('Y'), 'Corpus Cristi' => date('d/m/Y',$datas['corpus_cristi']), 'Dia da Independência' => '07/09/'.date('Y'), 'Nossa Senhora de Aparecida' => '12/10/'.date('Y'), 'Dia de Finados' => '02/11/'.date('Y'), 'Proclamação da República' => '15/11/'.date('Y'), 'Natal' => '25/12/'.date('Y') ); return $feriados; } ?>
Depois disso, você só precisa informar quantos dias você quer somar, a partir de qual data e se deseja considerar dias úteis ou não:
<!--?php /** * @author Rodrigo Régis Palmeira <regisbsb@gmail.com--> * @param int $soma - dias a serem somados * @param bolean $uteis - considera dias uteis - default false * @param date $data - data inicial válida - default date('d/m/Y') * @return string - data em formado d/m/Y */ function somarData($soma, $uteis = false, $data = null) { $ar = explode("/",$data); if (!empty($ar[0]) && !empty($ar[1]) && !empty($ar[2])) { if (checkdate($ar[1],$ar[0],$ar[2])) { $dia = $ar[0]; $mes = $ar[1]; $ano = $ar[2]; } else { return "Informe uma data válida!"; } } else { $dia = date('d'); $mes = date('m'); $ano = date('Y'); } if ($uteis) { $contDia = 0; $qtdDiasUteis = 0; while ($qtdDiasUteis < $soma) { $contDia++; if (($dias_da_semana = gmdate('w', strtotime('+'.$contDia.' day', mktime(0, 0, 0, $mes, $dia, $ano))) ) != '0' && $dias_da_semana != '6' && (!in_array(date('d/m/Y', mktime(0, 0, 0, $mes, $dia + $contDia, $ano)),retornarFeriados($ano)))) { $qtdDiasUteis++; } } $novaData = date("d/m/Y", mktime(0, 0, 0, $mes, $dia + $contDia, $ano)); } else { $novaData = date("d/m/Y", mktime(0, 0, 0, $mes, $dia + $soma, $ano)); } return $novaData; } ?>
É isso!
Espero ter ajudado!
