2013-04-08 28 views
5

Voglio calcolare tutte le domeniche tra due date date. Ho provato il seguente codice. Funziona bene se i giorni sono meno, ma se entro più giorni. Continua a elaborare e il tempo di esecuzione massimo supera il tempo, ma continua a funzionare anche se il tempo di esecuzione è di 200 secondi.calcola la domenica tra due date

codice

è

<?php 
$one="2013-01-01"; 
$two="2013-02-30"; 

$no=0; 
for($i=$one;$i<=$two;$i++) 
{ 

    $day=date("N",strtotime($i)); 
    if($day==7) 
    { 
    $no++; 
    } 
} 
echo $no; 

?> 

prega di aiuto.

+0

si può utilizzare un ciclo for in una stringa di data del genere? – andrewsi

+0

Non è possibile incrementare una stringa del genere. Guarda come gli altri lo fanno: http://stackoverflow.com/search?q=php+number+of+undays –

+0

È questo per un [problema euler del progetto (19)] (http://projecteuler.net/problem=19)? – HamZa

risposta

25

risposta di John Conde è corretto, ma qui è una soluzione più efficiente e mathy:

$start = new DateTime('2013-01-06'); 
$end = new DateTime('2013-01-20'); 
$days = $start->diff($end, true)->days; 

$sundays = intval($days/7) + ($start->format('N') + $days % 7 >= 7); 

echo $sundays; 

Fammi scomposizione per voi.

$start = new DateTime('2013-01-06'); 
$end = new DateTime('2013-01-20'); 

In primo luogo, creare alcuni DateTime oggetti, che sono potenti built-in PHP oggetti significava esattamente per questo tipo di problema.

$days = $start->diff($end, true)->days; 

successiva, utilizzare DateTime::diff trovare la differenza da $start a $end (passando true qui come secondo parametro assicura che questo valore è sempre positivo), e ottenere il numero di giorni tra loro.

$sundays = intval($days/7) + ($start->format('N') + $days % 7 >= 7); 

Ecco che arriva il grande - ma non è così complicato, davvero. Per prima cosa, sappiamo che esiste una domenica per ogni settimana, quindi abbiamo almeno $days/7 domeniche, arrotondate al più vicino int con intval.

Oltre a ciò, potrebbe esserci una domenica in un lasso di tempo inferiore a una settimana; ad esempio, dal venerdì al lunedì della settimana successiva contiene 4 giorni; uno di questi è una domenica. Quindi, a seconda di quando iniziamo e finiamo, potrebbe essercene un altro. Questo è facile da spiegare:

  • $start->format('N') (vedi DateTime::format) ci dà la ISO-8601 giorno della settimana per la data di inizio, che è un numero da 1 a 7 (1 è Lunedi, 7 è la Domenica) .
  • $days % 7 ci dà il numero di giorni rimanenti che non si dividono equamente in settimane.

Se il giorno di inizio e il numero di giorni rimanenti sono 7 o più, abbiamo raggiunto la domenica. Sapendo questo, dobbiamo solo aggiungere quell'espressione, che ci darà 1 se è vera o 0 se è falsa, poiché la aggiungiamo a un valore int.

E ce l'hai! Il vantaggio di questo metodo è che non richiede iterazioni ogni giorno tra i tempi prestabiliti e controlla se è domenica, il che ti farà risparmiare un sacco di calcoli e ti farà sembrare davvero intelligente. Spero possa aiutare!

+2

Questa parte non è vera 'Dal momento che $ giorni e 7 sono entrambi valori int, questo sarà sempre arrotondato per difetto al più vicino int. Devi usare una funzione rotonda come [floor()] (http://www.php.net/manual/en/function.floor.php) per aggirarlo, PHP non lo farà per te, prova ad esempio '$ end = new DateTime ('2013-02-20');' e l'output sarà decimale. – HamZa

+2

Hai assolutamente ragione, whoops! Ho dimenticato che stavo parlando di PHP per un secondo. –

+1

+1 per l'approccio intelligente e spiegarlo in dettaglio. –

8
<?php 
$no = 0; 
$start = new DateTime('2013-01-01'); 
$end = new DateTime('2013-04-30'); 
$interval = DateInterval::createFromDateString('1 day'); 
$period = new DatePeriod($start, $interval, $end); 
foreach ($period as $dt) 
{ 
    if ($dt->format('N') == 7) 
    { 
     $no++; 
    } 
} 
echo $no; 

See it in action

+0

grazie. Funziona. quindi non funzionava perché la stringa non veniva incrementata correttamente? –

+0

Fondamentalmente si. Lavorare con le stringhe, in particolare le date, è meglio lasciare alle funzionalità progettate per farlo. DateTime è progettato specificamente per lavorare con le date e, come puoi vedere, rende facile farlo. –

+0

sì, sì. Grazie. –

0

Ecco una soluzione se si desidera la domenica in un intervallo di date specifico.

function dateRange($begin, $end, $interval = null) 
{ 
    $begin = new DateTime($begin); 
    $end = new DateTime($end); 

    $end = $end->modify('+1 day'); 
    $interval = new DateInterval($interval ? $interval : 'P1D'); 

    return iterator_to_array(new DatePeriod($begin, $interval, $end)); 
} 

/* define date range */ 
$dates = dateRange('2018-03-01', '2018-03-31'); 

/* define weekdays */ 
$weekends = array_filter($dates, function ($date) { 
    $day = $date->format("N"); 
    return $day === '6' || $day === '7'; 
}); 

/* weekdays output */ 
foreach ($weekends as $date) { 
    echo $date->format("D Y-m-d") . "</br>"; 
} 

/* define sundays */ 
$sundays = array_filter($dates, function ($date) { 
    return $date->format("N") === '7'; 
}); 

/* sundays output */ 
foreach ($sundays as $date) { 
echo $date->format("D Y-m-d") . "</br>"; 
} 

/* define mondays */ 
$mondays = array_filter($dates, function ($date) { 
return $date->format("N") === '1'; 
}); 

/* mondays output */ 
foreach ($mondays as $date) { 
echo $date->format("D Y-m-d") . "</br>"; 
} 

basta cambiare il numero per i giorni desiderati nella vostra uscita:

Monday = 1 
Tuesday = 2 
Wednesday = 3 
Thursday = 4 
Friday = 5 
Saturday = 6 
Sunday = 7 
Problemi correlati