Guía 21 – Cálculo de días entre dos fechas

Este ejemplo espero que os ayude a algo muy habitual y es calcular los días entre dos fechas.

Este cálculo se da en muchos sistemas (gestión de vacaciones, reserva de hoteles, etc.). El cálculo de días entre dos fechas es una operación directa, no así conocer los tipos de días entre las fechas, es decir, si los días son:

  • Naturales
  • Laborables
  • De fin de semana (sábados y domingos)
  • Festivos

Objetivo

Calcular los días que hay entre dos fechas, identificando si son (naturales, laborables, de fin de semana y festivos).

DEMO: https://fhumanes.com/date_diference

Podéis utilizar los usuarios admin y user1. La password es lo mismo que el login.

Solución

El ejemplo está desarrollado en PHPRunner 10.2 para que llegue a más desarrolladores y su aspecto es:

 Se ha habilitado una tabla para indicar los festivos de la organización. Sólo los usuarios con perfil “admin” va a poder mantener la información de esta tabla.

La tabla de festivos es un registro por cada día festivo. Se ha indicado a través de calendario que no puede ser un día de sábado o domingo, para que no se puedan duplicar los festivos y los de fin de semana,

Se muestra en la imagen los días calculados de acuerdo a los tipos de días que están en el rango de las fechas (inicial y final)  que se informan.

En el ejemplo hay validaciones a nivel de JavaScript y de PHP. Se mostrará los códigos para la acción EDIT, por ser algo más compleja que la de ADD.

El evento: JavaScript Onload event:

var ctrl_date_init = Runner.getControl(pageid, 'date_init');
var ctrl_date_end = Runner.getControl(pageid, 'date_end');

this.on('beforeSave', function(formObj, fieldControlsArr, pageObj){
  var init = ctrl_date_init.getValue();
  var end = ctrl_date_end.getValue();
  if ( init > end ) {
      alert("It is necessary that the initial date is less than or equal to the end date");
      Runner.delDisabledClass(pageObj.saveButton ); // Activate again, button SAVE
      return false;
  } else {
      return true;
  }
});

El evento: before record updated:

$id_user = $values['date_user_id'];
$Dinit = $values['date_init'];
$Dend = $values['date_end'];
$id = $keys['id_date_permissions'];

// Control of the dates
if ( $Dinit > $Dend ) {
  $message = "The initial date must be equal to or less than the final date";
  return false;
}		

// Retrieve the holidays of the period
$holidays = array();
$rs = DB::Query("SELECT * FROM date_holidays where holiday between '$Dinit' and '$Dend'");
while( $data = $rs->fetchAssoc() )
{
  $holidays[] = $data['holiday'];
}

// Control of afforded dates
$rs = DB::Query(
"SELECT * FROM date_permissions
where `date_user_id` = $id_user and `id_date_permissions` <> $id
 and  (( date_init >= '$Dinit' and date_end <= '$Dend')
 or (date_init < '$Dinit' and date_end >= '$Dinit' )
 or (date_init > '$Dinit' and date_init <= '$Dend'))"
);
while( $data = $rs->fetchAssoc() )
{
  $message = "Some days of this range are already requested";
  return false;
}
//  Count the days of between dates
$count_N = 0;
$count_B = 0;
$count_H = 0;
$count_W = 0;

$start = strtotime($Dinit);
$end = strtotime($Dend);
while(date('Y-m-d', $start) <= date('Y-m-d', $end)){
  $count_N += 1;
  $string_init = date('Y-m-d', $start);
  if (in_array($string_init, $holidays)) {
    $count_H += 1; // Is holiday
  } else {	
    $d_w = date('N', $start); 
    $count_B += $d_w < 6 ? 1 : 0; //  Is Business 
    $count_W += $d_w < 6 ? 0 : 1; // Is weekend
  }
  $start = strtotime("+1 day", $start);
}

$values['natural_days'] = $count_N;
$values['business_days'] = $count_B;
$values['holidays'] = $count_H;
$values['weekdays'] = $count_W;

return true;

Para cualquier duda o cualquier otra necesidad,  contacta a través de email [email protected].

Os dejo el ejemplo para que lo podáis descargar en vuestros Windows y podáis realizar las pruebas y cambios que necesitéis.

Adjuntos

Archivo Tamaño de archivo Descargas
zip PHPRunner 10.2 y backup de base de datos. 550 KB 342

Blog personal para facilitar soporte gratuito a usuarios de PHPRunner