Calculando a diferença de dias úteis entre duas datas utilizando PHP

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;

}

 

 

Outra forma de resolver o mesmo problema utilizando DateTime

Agora que vimos como calcular a diferença de dias úteis utilizando timestamps e funções como mktime e strtotime, vamos conhecer uma forma alternativa de resolver o mesmo problema utilizando a classe DateTime do PHP.

A classe DateTime é nativa do PHP e facilita bastante o trabalho com datas, permitindo criar, comparar e percorrer intervalos de forma mais simples e legível.

Além disso, ela elimina a necessidade de trabalhar com timestamps diretamente.

Veja o exemplo abaixo:

 

function diasUteis($dataInicio, $dataFim, $feriados = [])

{

    $inicio = new DateTime($dataInicio);

    $fim = new DateTime($dataFim);

    $fim->modify(\'+1 day\'); // Inclui a data final no cálculo

    $intervalo = new DateInterval(\'P1D\');

    $periodo = new DatePeriod($inicio, $intervalo, $fim);

    $diasUteis = 0;

    foreach ($periodo as $data) {

        $diaSemana = $data->format(\'N\'); // 1 = segunda, 7 = domingo

        $dataStr = $data->format(\'Y-m-d\');

        // Ignora sábados e domingos

        if ($diaSemana >= 6) continue;

        // Ignora feriados

        if (in_array($dataStr, $feriados)) continue;

        $diasUteis++;

    }

    return $diasUteis;

}

// Exemplo de uso:

$feriados = [

    \'2021-01-01\', \'2021-04-21\', \'2021-05-01\',

    \'2021-09-07\', \'2021-10-12\', \'2021-11-02\',

    \'2021-11-15\', \'2021-12-25\',

];

echo diasUteis(\'2021-01-01\', \'2021-12-31\', $feriados);

 

Neste exemplo, utilizamos as classes DateTime, DateInterval e DatePeriod. A função DatePeriod permite criar um intervalo entre duas datas, e o DateInterval define o passo , neste caso, de um dia (P1D).

Dessa forma, podemos percorrer o intervalo completo sem precisar somar segundos manualmente.

Para verificar se o dia atual é um final de semana, usamos:

 

$diaSemana = $data->format(\'N\');

 

A função format(\'N\') retorna um número entre 1 (segunda-feira) e 7 (domingo). Assim, basta ignorar os dias 6 e 7 para não contar sábados e domingos.

Também usamos o formato Y-m-d ao comparar as datas com o array de feriados, garantindo que elas estejam no mesmo padrão e evitando erros de comparação.

O resultado final é o mesmo, mas o código fica mais limpo, legível e fácil de manter. Além disso, utilizando DateTime, é possível estender essa lógica para lidar com fusos horários, períodos personalizados e outros cálculos de datas com mais facilidade.

 

Outros conteudos que podem ser de seu interesse

Removendo acentos e caracteres especiais com PHP
07/06/2020PHP

Removendo acentos e caracteres especiais com PHP

Veja como remover acentos e caracteres especiais com PHP

Saiba mais...
Dicas de PHP e Laravel
23/06/2024PHP

Dicas de PHP e Laravel

Uma lista de sites para você aprender mais sobre PHP e Laravel

Saiba mais...
Calcular a diferença entre horas utilizando PHP
20/03/2022PHP

Calcular a diferença entre horas utilizando PHP

Aprenda como calcular a diferença de horas utilizando PHP

Saiba mais...

Conteúdo sobre banco de dados sem complicação!


Warning: Cannot modify header information - headers already sent by (output started at /home/storage/f/7d/a9/dbins/public_html/blog/post.php:101) in /home/storage/f/7d/a9/dbins/public_html/blog/ga4_track.php on line 11