Categorías
PHP

Función calculo dias sin contar fines semana ni vacaciones PHP

En esta entrada vamos a ver una función encargada de calculcar el número de dias desde una fecha dada hasta el momento actual. La particularidad de esta función es que no «contaremos» ni los fines de semana ni los dias de vacaciones que hayamos introducido previamente.

Sin más dilación pasemos a ver la función y vamos a analizarla con más detalle posteriormente.

// Calcula la diferencia en días dada una fecha y hasta el momento actual. No se tienen en cuenta ni fines de semana ni vacaciones. 
// Las vacaciones tienen que ser añadidas previamente al sistema, mediante un array.
// El parámetro $incial, es la fecha inicial desde la que queremos hacer el cálculo por ejemplo '2020-02-02 10:20:20'
function getDaysFromDateWithoutWEsHs(DateTime $inicial){
    //Obtenemos fecha actual para proceder con los cálculos.
    $final = new DateTime('now');
    //Descomentar si se quiere hacer un debug
    //echo $inicial->format('Y-m-d H:i:s')." - ".$final->format('Y-m-d H:i:s');
    
    //calculamos el intervalo
    $intervalo = $final->diff($inicial);
    //Una vez obtenido, obtendremos los dias naturales, sin diferenciación.
    $dias = $intervalo->days;
    // Creamos un periodo que sea "iterable", es decir que podamos iterar sobre el, a partir del periodo de las fechas de inicio y fin.(P1D significa periodos de un dia)
    $periodo = new DatePeriod($inicial, new DateInterval('P1D'), $final);
    // Array con vacacines, podemos añadir tantas como nos hagan falta, Aqui están introducidas algunas para lo que queda del 20,21 y 22.
    $vacaciones = array('2020-10-09','2020-10-12','2020-12-06','2020-12-07','2020-12-24','2020-12-25','2020-12-31','2021-01-01','2021-01-06','2021-03-19','2021-04-02','2021-04-05',
    '2021-09-12','2021-11-01','2021-12-06','2021-12-08','2021-12-25','2022-01-06','2022-04-15','2022-06-24','2022-08-15','2022-10-12','2022-11-01','2022-12-06','2022-12-08');

    foreach($periodo as $dt) {
        $curr = $dt->format('D');
        // Quitamos los sabados y domingos
        if ($curr == 'Sat' || $curr == 'Sun') {
            $dias--;
        }
        // (Opcionalmente) Quitamos los dias de vacaciones, si hemos alimentado el array.
        elseif (in_array($dt->format('Y-m-d'), $vacaciones)) {
            $dias--;
        }
    }
    return $dias; 
}

En el código podeis ver los pasos para conseguir nuestro objetivo.

  1. Pasamos fecha inicial
  2. Cálculamos fecha y tiempo actual.
  3. Cálculamos el itnervalo con «diff» y obtenemos un primer valor de «dias»
  4. Luego, calculamos el periodo donde poder iterar mediante «DatePeriod» y pasandole P1D para que haga periodos de 1 día.
  5. Iteramos por el periodo y le quitamos los fines de semana (Sat y Sun) y si hemos alimentado el array vacaciones, las vacaciones.
  6. Devolvemos el número de dias ya descontado.

Espero que os sirva de ayuda.