Calculando a diferença de dias úteis entre duas datas utilizando PHP
Neste artigo vamos ver como calcular a diferença de dias úteis entre duas datas utilizando PHP.
Primeiro vamos ver quais as datas iniciais e finais que vamos trabalhar.
$data1 = '2021-01-01';
$data2 = '2021-12-31';
Primeiro vamos ver se a data inicial não é maior que a data final.
$data_inicial = strtotime($data1);
$data_final = strtotime($data2);
if ($data_inicial > $data_final) {
echo "A data inicial é maior que a data final";
}
else {
//Codigo a ser inserido
}
Nosso próximo passo é criar um array auxiliar que contenha todos os feriados contidos dentro do intervalo de datas informado. Alguns feriados tem data fixa, e outros tem data variável. Começando pelos feriados de data fixa.
$feriados = array();
$ano_inicial = date('Y', $data_inicial);
$ano_final = date('Y', $data_final);
$ano = $ano_inicial;
for ($x = $ano_inicial; $x <= $ano_final; $x++) {
//Feriados com data fixa
$feriados[] = mktime(0, 0, 0, 1, 1, $ano);
$feriados[] = mktime(0, 0, 0, 4, 21, $ano);
$feriados[] = mktime(0, 0, 0, 5, 1, $ano);
$feriados[] = mktime(0, 0, 0, 9, 7, $ano);
$feriados[] = mktime(0, 0, 0, 10, 12, $ano);
$feriados[] = mktime(0, 0, 0, 11, 2, $ano);
$feriados[] = mktime(0, 0, 0, 11, 15, $ano);
$feriados[] = mktime(0, 0, 0, 12, 25, $ano);
}
Neste exemplo foi criado um array auxiliar chamado $feriados. Para adicionar cada data fixa no array, criamos a data utilizando a funçao mktime. Ele cria um timestamp UNIX com a data informada. Seus parâmetros na ordem são hora, minuto, segundo, mês, dia e ano. Para fins didáticos, adicionamos as datas manualmente. Você pode refatorar este código depois e criar uma função para simplicar este processo.
Agora vamos ver os feriados variáveis. Os feriados com data variável dependem da data da páscoa.
for ($x = $ano_inicial; $x <= $ano_final; $x++) {
$pascoa = easter_date($ano);
$dia_pascoa = date('j', $pascoa);
$mes_pascoa = date('n', $pascoa);
$ano_pascoa = date('Y', $pascoa);
//Feriados com data variável
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 48, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 47, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 2 , $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa + 60, $ano_pascoa);
$ano++;
}
Os feriados variáveis são a páscoa, a sexta-feira santa, os dias de carnaval e o Corpus Christi
Agora que temos os feriados, podemos verificar a quantidade de dias uteis entre duas datas.
$fim_semana = 0;
$numero_dias = 0;
$numero_feriados = 0;
while ($data_inicial <= $data_final) {
$numero_dias++; //Numero de dias do intervalo informado
if (in_array(date("y-m-d", $data_inicial), $feriados)) {
$numero_feriados++;
}
$dia_semana = date("N", $data_inicial);
if ($dia_semana > 5) { // 6 e 7 são sábado e domingo
$fim_semana++;
};
$data_inicial += 86400; // +1 dia
};
$dias_trabalho = $numero_dias - $fim_semana - $numero_feriados;
Para o calculo de dias fizemos um loop usando WHILE entre a data inicial e a data final, e fizemos o incremento da data em 1 dia, somando 86400 segundos a data informada.
Para validar se a data atual é um feriado, utilizamos a função in_array para verificar se aquela data existe no array de feriados.
if (in_array(date("y-m-d", $data_inicial), $feriados)) {
$numero_feriados++;
}
Em nosso exemplo não consideremos o sábado e o domingo como dia úteis. Para verificar o dia da semana da data informada, utilizamos a função DATE desta forma:
$dia_semana = date("N", $data_inicial);
O retorno é um número inteiro. Ele vai retornar 6 para sábado e 7 para domingo.
O código completo fica da seguinte forma:
$data1 = '2021-01-01';
$data2 = '2021-12-31';
$data_inicial = strtotime($data1);
$data_final = strtotime($data2);
if ($data_inicial > $data_final) {
echo "A data inicial é maior que a data final";
return 0;
} else {
$feriados = array();
$ano_inicial = date('Y', $data_inicial);
$ano_final = date('Y', $data_final);
$ano = $ano_inicial;
for ($x = $ano_inicial; $x <= $ano_final; $x++) {
$pascoa = easter_date($ano);
$dia_pascoa = date('j', $pascoa);
$mes_pascoa = date('n', $pascoa);
$ano_pascoa = date('Y', $pascoa);
//Feriados com data fixa
$feriados[] = mktime(0, 0, 0, 1, 1, $ano);
$feriados[] = mktime(0, 0, 0, 4, 21, $ano);
$feriados[] = mktime(0, 0, 0, 5, 1, $ano);
$feriados[] = mktime(0, 0, 0, 9, 7, $ano);
$feriados[] = mktime(0, 0, 0, 10, 12, $ano);
$feriados[] = mktime(0, 0, 0, 11, 2, $ano);
$feriados[] = mktime(0, 0, 0, 11, 15, $ano);
$feriados[] = mktime(0, 0, 0, 12, 25, $ano);
//Feriados com data variável
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 48, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 47, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 2 , $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa, $ano_pascoa);
$feriados[] = mktime(0, 0, 0, $mes_pascoa, $dia_pascoa + 60, $ano_pascoa);
$ano++;
}
$fim_semana = 0;
$numero_dias = 0;
$numero_feriados = 0;
while ($data_inicial <= $data_final) {
$numero_dias++; //Numero de dias do intervalo informado
if (in_array(date("y-m-d", $data_inicial), $feriados)) {
$numero_feriados++;
}
$dia_semana = date("N", $data_inicial);
if ($dia_semana > 5) { // 6 e 7 são sábado e domingo
$fim_semana++;
};
$data_inicial += 86400; // +1 dia
};
$dias_trabalho = $numero_dias - $fim_semana - $numero_feriados;
echo $dias_trabalho;
}