Calculation of working days

Asked

Viewed 1,579 times

2

Guys, I have some methods in PHP that return me the number of days between the initial date and the final date, however, I would like to receive as parameter, only initial date and number of days and receive after, the final day

public function index()
{
    $yDataInicial = date('d/m/Y'); 
    $yDataFinal = '28/04/2019';

    $diaFDS = 0; //dias não úteis(Sábado=6 Domingo=0)
    $calculoDias = $this->CalculaDias($yDataInicial, $yDataFinal); //número de dias entre a data inicial e a final
    $diasUteis = 0;

    while($yDataInicial != $yDataFinal){
        $diaSemana = date("w", $this->dataToTimestamp($yDataInicial)); 
        if($diaSemana == 0 || $diaSemana == 6){ 
            //se SABADO OU DOMINGO, SOMA 01
            $diaFDS++;
        }else{
        //senão vemos se este dia é FERIADO
            for($i=0; $i<=12; $i++){
                if($yDataInicial == $this->Feriados(date("Y"),$i)){
                $diaFDS++;   
                }
            }
        }
        $yDataInicial = $this->Soma1dia($yDataInicial); //dia + 1
    }
    $final =  $calculoDias - $diaFDS;
    return view('welcome', compact('final'));
}



public function CalculaDias($xDataInicial, $xDataFinal)
{
    $time1 = $this->dataToTimestamp($xDataInicial);  
    $time2 = $this->dataToTimestamp($xDataFinal);  

    $tMaior = $time1 > $time2 ? $time1 : $time2;  
    $tMenor = $time1 < $time2 ? $time1 : $time2;  
    $diff = $tMaior-$tMenor;  
    $numDias = $diff/86400; //86400 é o número de segundos que 1 dia possui  
    return $numDias; // dias corridos     
}


public function dataToTimestamp($data)
{
    $ano = substr($data, 6,4);
    $mes = substr($data, 3,2);
    $dia = substr($data, 0,2);
    return mktime(0, 0, 0, $mes, $dia, $ano);
}

public function feriados($ano,$posicao) 
{
    $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 (
        '01/01',
        '02/02', // Navegantes
        date('d/m',$datas['carnaval']),
        date('d/m',$datas['sexta_santa']),
        date('d/m',$datas['pascoa']),
        '21/04',
        '01/05',
        date('d/m',$datas['corpus_cristi']),
        '20/09', // Revolução Farroupilha \m/
        '12/10',
        '02/11',
        '15/11',
        '25/12',
    );

    return $feriados[$posicao]."/".$ano;
}

public function Soma1dia($data){   
    $ano = substr($data, 6,4);
    $mes = substr($data, 3,2);
    $dia = substr($data, 0,2);
    return   date("d/m/Y", mktime(0, 0, 0, $mes, $dia+1, $ano));
}

1 answer

2


See if it is what you want, will pick up the working days, the amount and the last day. From an initial date and within a number of days.

<?php

function getListaDiasFeriado($ano = null) {

    if ($ano === null) {
        $ano = intval(date('Y'));
    }

    $pascoa = easter_date($ano); // retorna data da pascoa do ano especificado
    $diaPascoa = date('j', $pascoa);
    $mesPacoa = date('n', $pascoa);
    $anoPascoa = date('Y', $pascoa);

    $feriados = [
        // Feriados nacionais fixos
        mktime(0, 0, 0, 1, 1, $ano),   // Confraternização Universal
        mktime(0, 0, 0, 4, 21, $ano),  // Tiradentes
        mktime(0, 0, 0, 5, 1, $ano),   // Dia do Trabalhador
        mktime(0, 0, 0, 9, 7, $ano),   // Dia da Independência
        mktime(0, 0, 0, 10, 12, $ano), // N. S. Aparecida
        mktime(0, 0, 0, 11, 2, $ano),  // Todos os santos
        mktime(0, 0, 0, 11, 15, $ano), // Proclamação da republica
        mktime(0, 0, 0, 12, 25, $ano), // Natal
        //
        // Feriados variaveis
        mktime(0, 0, 0, $mesPacoa, $diaPascoa - 48, $anoPascoa), // 2º feria Carnaval
        mktime(0, 0, 0, $mesPacoa, $diaPascoa - 47, $anoPascoa), // 3º feria Carnaval 
        mktime(0, 0, 0, $mesPacoa, $diaPascoa - 2, $anoPascoa),  // 6º feira Santa  
        mktime(0, 0, 0, $mesPacoa, $diaPascoa, $anoPascoa),      // Pascoa
        mktime(0, 0, 0, $mesPacoa, $diaPascoa + 60, $anoPascoa), // Corpus Christ
    ];

    sort($feriados);

    $listaDiasFeriado = [];
    foreach ($feriados as $feriado) {
        $data = date('Y-m-d', $feriado);
        $listaDiasFeriado[$data] = $data;
    }

    return $listaDiasFeriado;
}

function isFeriado($data) {
    $listaFeriado = getListaDiasFeriado(date('Y', strtotime($data)));
    if (isset($listaFeriado[$data])) {
        return true;
    }

    return false;
}

function getDiasUteis($aPartirDe, $quantidadeDeDias = 30) {
    $dateTime = new DateTime($aPartirDe);

    $listaDiasUteis = [];
    $contador = 0;
    while ($contador < $quantidadeDeDias) {
        $dateTime->modify('+1 weekday'); // adiciona um dia pulando finais de semana
        $data = $dateTime->format('Y-m-d');
        if (!isFeriado($data)) {
            $listaDiasUteis[] = $data;
            $contador++;
        }
    }

    return $listaDiasUteis;
}

$listaDiasUteis = getDiasUteis("2019-04-17", 15);
$ultimoDia = end($listaDiasUteis);

echo "<pre>";
print_r($listaDiasUteis);
echo "</pre>";

echo "ULTIMO DIA: " . $ultimoDia;

Function of calculation of the withdrawn holiday from here.

See working here

  • Thank you very much for answering, I found good your code, I tested here, very good, however, I will give you an example, imagining that the initial date is today 17/04/2019, I determined the amount of running days 15, the final date should be 08/05/2019, I mean, his code is great but he’s counting weekends and holidays tbm, as could take out the weekends and holidays, thank you....

  • initial date 17/04/2019, result : ["18/04/2019","19/04/2019","22/04/2019","23/04/2019","24/04/2019","25/04/2019","26/04/2019","29/04/2019","30/04/2019","01/05/2019","02/05/2019"] need to take weekends and holidays, and the result has to be day 08/05/2019

  • Well, doing tests, I was able to solve part of the problem, I only inserted the counter ... if ($numDiaDaSemana != 0 && $numDiaDaSemana != 6) { // if it is not Saturday or Sunday $listDiasUteis[] = $datetime->format(’d/m/Y'); $counter++; } so it brings me the final date and really withdrew the weekends, I will try to create a function to remove the holidays now, thanks friend, helped ....

  • @Rafaelmoura in this case just change the line $datetime->Modify('+1 day') for $datetime->Modify('+1 weekday') and it already increases without considering the weekends. I changed, take a look.

  • but he runs out of the same accountant Diego ?

  • pq I took the contact++ and it operates nothing

  • and another thing, weekday with the counter out of the IF, putting start date = 17/04/2019 and 8 days, it show the result from the day 23/04/2019 until the end 11/06/2019

  • I put the holiday function too, can copy everything and replace. Putting 17/04 should come 08/05, right?

  • let me see here , 1 minute

  • you know what’s curious, if I put "+1 day weekday" with the counter inside the IF, it starts from the day 23/04/2019", and that I put today’s day with amounts Ias = 8, I think the weekday doesn’t apply here

  • starting today, minus the weekday and quantityDia = 8, it works out looks ["18/04/2019","19/04/2019","22/04/2019","23/04/2019","24/04/2019","25/04/2019","26/04/2019","29/04/2019"]

  • @Rafaelmoura syntax is $datetime->Modify('+1 weekday'); not $datetime->Modify('+1 day weekday');

  • truth, that lack of attention, worked now ....

  • this holiday function in the first code I sent, which has $year and $position parameters apply, or you have a specific, please .... ?

  • @Rafaelmoura I added the holiday calculation function, gives a look.

  • You’re a genius, now it’s okay, you saved my day, very good, thank you very much, I hope the community enjoys the code, thank you.

  • @Rafaelmoura I’m glad it worked out! Abs

Show 12 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.