Calcolo giorni lavorativi tra due date (escluse le feste comandate)

  • Creatore Discussione Creatore Discussione Maures
  • Data di inizio Data di inizio

Maures

Utente Attivo
25 Mar 2015
45
0
0
Buongiorno a tutti,
devo creare uno script per il calcolo dei giorni lavorativi fra due date.
Sfruttando questo codice sono riuscito nel mio intento, ma ora mi si pone un problema.
Come potete vedere, il codice inserisce manualmente in un array le feste, costringendo poi il programmatore a modificarle di volta in volta ogni anno. inoltre se dovessi fare il calcolo a cavallo di due anni, non funzionerebbe. come rendere dinamico questo array?
Come aggiungo a questo array anche la pasqua, che non è mai nello stesso giorno?

Grazie a tutti.
 
ciao
questa considera festivi solo il sabato e la domenica
se vuoi anche le altre devi farti un array con le date delle feste (es 25/04, 01/06....)
poi con date("d/m",$timestamp) verifichi che non sia sabato o domenica ma se festa decrementi
il problema l'hai con la data di pasqua variabile di anno in anno

PHP:
<?php
function giorni_lav($d1,$d2){
	$d_i=explode("-",$d1);//attento al formato delle date che hai tu
	$d_f=explode("-",$d2);
	$d_i_ts=mktime(0,0,0,$d_i[1],$d_i[0],$d_i[2]);//espressa in secondi TIME STAMP
	$d_f_ts=mktime(0,0,0,$d_f[1],$d_f[0],$d_f[2]);
	$g_ts= 24*60*60;//secondi in un giorno
	$quanti_giorni=(int)(($d_f_ts-$d_i_ts)/$g_ts-1);//giorni totali compresi i festivi
	while($d_i_ts < $d_f_ts){
		//7=domenica, 6=sabato
		if(date("N",$d_i_ts)== '6' || date("N",$d_i_ts)== '7'){
			$quanti_giorni -= 1;// se trovo un sabato o una domenica decremento l'intervallo
		}
		$d_i_ts +=$g_ts;//incrementa l'iniziale di un giorno
	}
	return $quanti_giorni;
}
// test
$data_inizio="01-06-2015";
$data_fine="13-06-2015";
echo "giornate lavorative ".giorni_lav($data_inizio,$data_fine);
//OUTPUT giornate lavorative 9
?>
 
Ciao, anche il lunedi di pasqua è festa. credo
Puoi provare a calcolarlo con questa funzione.
Secondo me nel link che hai postato, la seconda soluzione che hanno proposto ( number_of_working_days() ) si adatta meglio alle tue esigenze ed è molto più semplice da modificare. Necessita però di php 5.3.0 o superiore visto l'utilizzo della classe DateTime()
 
ciao
criric ha ragione, che cada di domenica la pasqua è risaputo e quindi basterebbe calcolarla come domenica, ma anche lunedì è festivo e quindi da determinare quindi secondo me si dovrebbe:
determinare la datqa della pasqua e aggiungere un giorno
verificare se la pasqua cade tra le due date richieste e togliere dai lavorativi il lunedi
se ti interessa vado a ripescare una funzione che avevo fatto e che calcolava la data per ogni anno con l'algoritomo di gaus

@criric
la funzione number_of_working_days() non credo che consideri le festività locali e quindi secondo me da fare sempre un array con tali date
 
Si l'array delle festività locali è inevitabile.
Avevo iniziato a buttar gìù un idea ma poi mi sono bloccato, posto la bozza incompleta
PHP:
function Pasqua($anno) {

    $nc = intval($anno / 100);
    $nn = $anno - 19 * intval($anno / 19);
    $nk = intval(($nc - 17) / 25);
    $ni1 = $nc - intval($nc / 4) - intval(($nc - $nk) / 3) + 19 * $nn + 15;
    $ni2 = $ni1 - 30 * intval($ni1 / 30);
    $ni3 = $ni2 - intval($ni2 / 28) * (1 - intval($ni2 / 28) * intval(29 / ($ni2 + 1)) * intval((21 - $nn) / 11));
    $nj1 = $anno + intval($anno / 4) + $ni3 + 2 - $nc + intval($nc / 4);
    $nj2 = $nj1 - 7 * intval($nj1 / 7);
    $nl = $ni3 - $nj2;

    $mese = 3 + intval(($nl + 40) / 44);
    $giorno = $nl + 28 - 31 * intval($mese / 4);

    return $anno . "-" . $mese . "-" . $giorno;
}

function festivo($data = false) {

    $check = new DateTime();
    if (!$check->createFromFormat('Y-m-d', $data)) {
        return "data non valida";
    }

    $d = new DateTime($data);
    $pasqua = new DateTime(Pasqua($d->format("Y")));

    $festivita = array(
        "01-01" => "Capodanno",
        "01-06" => "Epifania",
        "04-25" => "Festa della liberazione",
        $pasqua->format("m-d") => "Pasqua",
        $pasqua->modify("+1 day")->format("m-d") => "Lunedi' dell'Angelo",
        "05-01" => "Festa dei lavoratori",
        "06-02" => "Festa della repubblica",
        "08-15" => "Ferragosto",
        "11-01" => "Festa di tutti i santi",
        "12-08" => "Festa dell'immacolata",
        "12-25" => "Natale",
        "12-26" => "Giorno di Santo Stefano"
    );
    if (!$data) {
        return $festivita;
    }
    if (array_key_exists($d->format('m-d'), $festivita)) {
        return $festivita[$d->format('m-d')];
    }
    if ($d->format('w') == 0) {
        return "Domenica";
    }

    return false;
}

var_dump(festivo(date("Y-m-d")));
edit:
ops, avevo troncato, cmq ho sbagliato script
 
Ultima modifica:
vedi se ti va bene,
ciao
Marino

PHP:
<?php
  $holidayDays = 
  [
    "*-01-01"=>"Capodanno",
    "*-01-06"=>"Epifania", 
    "*-04-25"=>"Liberazione", 
    "*-05-01"=>"Festa Lavoratori", 
    "*-06-02"=>"Festa della Repubblica", 
    "*-08-15"=>"Ferragosto", 
    "*-11-01"=>"Tutti Santi", 
    "*-12-08"=>"Immacolata", 
    "*-12-25"=>"Natale", 
    "*-12-26"=>"Santo Stefano",
    "*-08-16"=>"Patrono"
  ];

$DataInizio	= '2015-01-01';
$DataFine	= '2015-12-31';

$AnnoInizio	= date('Y', strtotime($DataInizio));
Pasqua($AnnoInizio);
$holidayDays[$AnnoInizio."-".$Lmese."-".$Lgiorno] = "Pasquetta ".$AnnoInizio;

$AnnoFine	= date('Y', strtotime($DataFine));
if($AnnoFine != $AnnoInizio) {
  Pasqua($AnnoFine);
  $holidayDays[$AnnoFine."-".$Lmese."-".$Lgiorno] = "Pasquetta ".$AnnoFine;
}
echo $DataInizio." --> ".$DataFine."<br /><br />";
echo "number_of_working_days = ".number_of_working_days($DataInizio, $DataFine, $holidayDays)."<br /><br />";
print_r ($holidayDays);


function number_of_working_days($from, $to, $holidayDays, $workingDays = [1, 2, 3, 4, 5]) 
{
  $holidayDays = array_flip($holidayDays);

  $from = new DateTime($from);
  $to = new DateTime($to);
  $to->modify('+1 day');
  $interval = new DateInterval('P1D');
  $periods = new DatePeriod($from, $interval, $to);

  $days = 0;
  foreach ($periods as $period) {
    if (!in_array($period->format('N'),   $workingDays)) continue;
    if ( in_array($period->format('Y-m-d'), $holidayDays)) continue;
    if ( in_array($period->format('*-m-d'), $holidayDays)) continue;
    $days++;
  }
  return $days;
}

function Pasqua($anno) { 
  global $Pmese,$Pgiorno,$Lmese,$Lgiorno; 

  $nc=intval($anno/100); 
  $nn=$anno-19*intval($anno/19); 
  $nk=intval(($nc-17)/25); 
  $ni1=$nc-intval($nc/4)-intval(($nc-$nk)/3)+19*$nn+15; 
  $ni2=$ni1-30*intval($ni1/30); 
  $ni3=$ni2-intval($ni2/28)*(1-intval($ni2/28)*intval(29/($ni2+1))*intval((21-$nn)/11)); 
  $nj1=$anno+intval($anno/4)+$ni3+2-$nc+intval($nc/4); 
  $nj2=$nj1-7*intval($nj1/7); 
  $nl=$ni3-$nj2; 

  $Pmese=3+intval(($nl+40)/44); 
  $Pgiorno=$nl+28-31*intval($Pmese/4); 

  if ($Pmese == 3 and $Pgiorno == 31) { $Lmese = 4; $Lgiorno = 1; } 
  else { $Lmese = $Pmese; $Lgiorno = $Pgiorno + 1; } 
} 
?>

Codice:
2015-01-01 --> 2015-12-31

number_of_working_days = 255

Array ( [*-01-01] => Capodanno [*-01-06] => Epifania [*-04-25] => Liberazione [*-05-01] => Festa Lavoratori [*-06-02] => Festa della Repubblica [*-08-15] => Ferragosto [*-11-01] => Tutti Santi [*-12-08] => Immacolata [*-12-25] => Natale [*-12-26] => Santo Stefano [*-08-16] => Patrono [2015-4-6] => Pasquetta 2015 )
 

Discussioni simili