2015-06-09 18 views
6

Ho un codice PHP per calcolare il numero di giorni tra due date specifiche. La differenza non dovrebbe contare domenica e sabato. Inoltre, ho una serie di date, che include le festività, che devono essere saltate.Errore calcolo differenza giorni PHP

Ho dato la data di inizio come 01-05-2015 e la data di fine come 01-06-2015. Ho dato tutti i giorni nel mese di maggio come array. Quindi la differenza dovrebbe essere 1 giorno. Ma sto ottenendo l'output come 7. Qual è il problema? Ecco il codice.

function dateRange($first, $last) { 
    $dates = array(); 
    $current = strtotime($first); 
    $now = $current; 
    $last = strtotime($last); 
    while($current <= $last) { 
     if (date('w', $current) != 0){ 
      $dates[] = date('d-m-Y', $current); 
     } 
     $current = strtotime('+1 day', $current); 
    } 
    unset($dates[0]); 
    return $dates; 
} 


$datea = "01-05-2015"; 
$date = "01-06-2015"; 
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015"); 

$datesarray = dateRange($datea, $date); 
$result = array_diff($hdsarray,$datesarray); 
$date_diff = sizeof($result); 

echo $date_diff; 

Grazie in anticipo ... :)

+2

Qui ci sono alcuni problemi. Prima di tutto, inizierò con una domanda: perché stai disattivando $ date [0]? Detto questo, array_diff non funzionerà, perché la data $ hsdarray "1-05-2015" è DIVERSA da "01-05-2015", quindi la tua differenza non funzionerà. Un altro problema: poiché si escludono le domeniche (e probabilmente il sabato, ma non lo vedo nel codice), array_diff uscirà ALMENO: 16-05-2015 (sabato), 23-05-2015 (sabato) e 30-05-2015 (sabato). – briosheje

risposta

3

Il problema solo che posso vedere è in uso di array_diff, in realtà include il sabato e domenica che è escluso dal dateRange funzione, se non si trovano in lista di vacanze .

Invece è possibile passare le date delle vacanze nella funzione dateRange e filtrare laggiù.

function dateRange($first, $last, $excludeDates) { 
    $dates = array(); 
    $current = strtotime($first); 
    $now = $current; 
    $last = strtotime($last); 
    while($current <= $last) { 
     if (date('w', $current) != 0 && date('w', $current) != 6 && !in_array(date('j-m-Y', $current), $excludeDates)){ 
      $dates[] = date('d-m-Y', $current); 
     } 
     $current = strtotime('+1 day', $current); 
    } 
    // unset($dates[0]); 
    return $dates; 
} 

$datea = "01-05-2015"; 
$date = "01-06-2015"; 
$hdsarray = array("1-05-2015","2-05-2015","4-05-2015","5-05-2015","7-05-2015","8-05-2015","9-05-2015","11-05-2015","12-05-2015","14-05-2015","15-05-2015","16-05-2015","18-05-2015","19-05-2015","21-05-2015","22-05-2015","23-05-2015","25-05-2015","26-05-2015","28-05-2015","29-05-2015","30-05-2015"); 
$datesarray = dateRange($datea, $date, $hdsarray);print_r($datesarray); 

Risultato:

Array 
(
    [0] => 06-05-2015 
    [1] => 13-05-2015 
    [2] => 20-05-2015 
    [3] => 27-05-2015 
    [4] => 01-06-2015 
) 

Tutte le 5 date viene in seguito, non sono seduto, sole, e, inoltre, non c'è nella lista vacanze.

0

Sembra che ci siano diversi problemi qui. In primo luogo, come sottolineato da altri, la condizione:

if (date('w', $current) != 0){ 

verifica solo i domeniche, se si deve anche includere del Sabato che dovrebbe essere:

if (date('w', $current) != 0 && date('w', $current) != 6){ 

In secondo luogo, sembra che la matrice $hdsarray non contiene tutti i giorni di maggio. Sembra che manchino tutti i mercoledì.

Il terzo problema è che si utilizza array_diff su due array, uno contenente le date e gli altri contenenti stringhe. Dalla documentazione:

Due elementi sono considerati uguali se e solo se (string) $ elem1 === (string) $ elem2. In parole: quando la rappresentazione della stringa è la stessa.

Nella tua $hdsarray si utilizza "1-05-2015" per indicare il primo giorno del mese, mentre:

echo date('d-m-Y', strtotime("1-05-2015")); 

risultati in "01-05-2015". È necessario aggiungere un ulteriore 0 in $hdsarray per queste date o lavorare con le date.

Ultimo ma non meno importante, l'algoritmo corrente non funzionerà correttamente se lo $hdsarray contiene le date per un sabato o una domenica, il risultato di array_diff conterrà comunque queste date. Poiché si desidera filtrare il risultato di daterange, la funzione array_filter potrebbe essere più adatta.

0

Nonostante una risposta è già stata fornita, ecco un piccolo frammento con una movimentazione tutto di classe per voi:

<?php 

class dateRange { 
    protected $start, $end, $daysToExclude, $datesToExclude; 

    function __construct($dateStart, $dateEnd, $daysToExclude, $datesToExclude) { 
     $this->start   = $dateStart; 
     $this->end    = $dateEnd; 
     $this->daysToExclude = $daysToExclude; 
     $this->datesToExclude = $this->fixFormat($datesToExclude); 
    } 

    public function getRangeLength ($callback = null) { 
     $tmp = array(); 

     $now = strtotime($this->start); 
     $to  = strtotime($this->end); 

     while ($now <= $to) { 
      if (!in_array(date("w", $now), $this->daysToExclude)) { 
       $tmp[] = date('d-m-Y', $now); 
      } 
      $now = strtotime('+1 day', $now); 
     } 

     is_callable($callback) && call_user_func($callback, array_diff($tmp,$this->datesToExclude)); 

     return count(array_diff($tmp,$this->datesToExclude)); 
    } 

    private function fixFormat($el) { 
     if (!is_array($el)) { 
      return false; 
     } 
     else { 
      foreach ($el as &$value) { 
       $value = date("d-m-Y",strtotime($value)); 
      } 
      return $el; 
     } 
    } 
} 

?> 

ho deciso di mantenere la logica corrente (utilizzando date_diff), ma ho pensato che, in il futuro, potresti avere il tuo capo che ti dice "Sai cosa? Non voglio avere lunedì e lì" quindi, con il sistema attuale, dovrai modificare la tua funzione manualmente e, forse, non ti ricorderai più quello che hai fatto.

La classe sopra aspetta quattro parametri:

  • dateStart (formato GMA)
  • dateEnd (formato GMA)
  • daysToExclude (array con ID dei giorni per escludere -> esempio matrice (0, 6) per escludere sabato e domenica).
  • dateToExclude (matrice con le date da escludere, ogni formato supportato).

La classe correggerà automaticamente le date Formato di array ExExclude per consentire l'utilizzo di date_diff.

Ecco un esempio usarlo, seguendo il caso:

<?php 

    $dateStart  = "01-05-2015"; 
    $dateEnd  = "01-06-2015"; 
    $daysToExclude = array(0,6); 
    $exclusions = array(
       "1-05-2015", 
       "2-05-2015", 
       "4-05-2015", 
       "5-05-2015", 
       "7-05-2015", 
       "8-05-2015", 
       "9-05-2015", 
       "11-05-2015", 
       "12-05-2015", 
       "14-05-2015", 
       "15-05-2015", 
       "16-05-2015", 
       "18-05-2015", 
       "19-05-2015", 
       "21-05-2015", 
       "22-05-2015", 
       "23-05-2015", 
       "25-05-2015", 
       "26-05-2015", 
       "28-05-2015", 
       "29-05-2015", 
       "30-05-2015" 
      ); 
      $dateRange = new dateRange($dateStart, $dateEnd, $daysToExclude, $exclusions); 
      echo $dateRange->getRangeLength(); 
?> 

Il codice sopra uscite 5.

La getRangeLength funzione accetta anche un callback e tornerà la array risultante dell'operazione date_diff , in modo da poter anche:

$dateRange->getRangeLength(function($res) { 
    echo "Literal output: <br />"; 
    print_r($res); 
    echo "<br />count is: " . count($res); 
}); 

Le uscite di cui sopra:

Literal output: 
Array ([3] => 06-05-2015 [8] => 13-05-2015 [13] => 20-05-2015 [18] => 27-05-2015 [21] => 01-06-2015) 
count is: 5 

Quindi, se in seguito sarà necessario rimuovere il lunedì troppo, si sarà in grado di fare facilmente che cambiando daysToExclude a array(0,1,6);

Spero che questo sarà utile per chiunque altro che avrà bisogno di questo, nonostante una risposta valida è già stato pubblicato

Il tuo problema originale, in ogni caso, è stato più o meno legati alla funzione array_diff, che non stava facendo il suo lavoro a causa del fatto che le stringhe di data non erano compatibili, perché "2015/01/01" è diverso da "01-01-2015", a meno che non si convertano ENTRAMBI di essi a volte e poi di nuovo alle date.

Problemi correlati