2009-06-10 11 views
64

Se si dispone di un numero $start_date e $end_date, come è possibile verificare se una data data dall'utente rientra in tale intervallo?Come verificare se una data è in un determinato intervallo?

ad es.

$start_date = '2009-06-17'; 

$end_date = '2009-09-05'; 

$date_from_user = '2009-08-28'; 

Al momento sono le date stringhe, sarebbe aiutare a convertirli in numeri interi timestamp?

+0

Sarebbe utile, allora si avrebbe accesso a tutte le funzioni di manipolazione di data ci sono. – ChrisF

+3

Semplicemente con la limitazione del timestamp dato che i timestamp di Unix iniziano all'epoca, che è il 1 gennaio 1970 (1970-01-01), quindi potresti avere un comportamento divertente per verificare le date prima del 1970. –

+1

@Shadi Sai che esiste qualcosa Numeri negativi, giusto? –

risposta

96

Conversione in data e ora è il modo di andare bene, utilizzando strtotime, ad esempio

$start_date = '2009-06-17'; 

$end_date = '2009-09-05'; 

$date_from_user = '2009-08-28'; 

check_in_range($start_date, $end_date, $date_from_user); 


function check_in_range($start_date, $end_date, $date_from_user) 
{ 
    // Convert to timestamp 
    $start_ts = strtotime($start_date); 
    $end_ts = strtotime($end_date); 
    $user_ts = strtotime($date_from_user); 

    // Check that user date is between start & end 
    return (($user_ts >= $start_ts) && ($user_ts <= $end_ts)); 
} 
2

convertirli in date o interi timestamp e poi basta controllare di $ date_from_user è < = $ data_finale e> = $ start_date

+3

Potrebbe chiarire "convertirli in date"? Come lo faresti? Pensavo che PHP non avesse un tipo di data? – meleyal

3

convertire sia risale al timestamp poi fare

pseudocodice:

if date_from_user > start_date && date_from_user < end_date 
    return true 
+0

Potrebbe essere necessario modificarlo in modo da includere anche start_date e end_date nell'intervallo. In questo momento se date_from_user è uguale a, non verrà conteggiato. – TheTXI

+0

L'OP non ha specificato intervalli inclusi o esclusivi, quindi lascerò a loro scegliere quale strategia utilizzare – Glen

4
$startDatedt = strtotime($start_date) 
$endDatedt = strtotime($end_date) 
$usrDatedt = strtotime($date_from_user) 

if($usrDatedt >= $startDatedt && $usrDatedt <= $endDatedt) 
{ 
    //..falls within range 
} 
+0

Ciò non includerà alcuna corrispondenza esatta con la data di inizio o la data di fine – TheTXI

+0

thx. errore di battitura. ho risolto il codice –

+0

OP non ha chiesto le partite incluse. –

46

Non è necessario convertire al timestamp per fare il confronto, dato che le stringhe sono convalidati come le date in formato canonico 'AAAA-MM-DD'.

Questo test funziona:

(($date_from_user >= $start_date) && ($date_from_user <= $end_date)) 

dato:

$start_date  = '2009-06-17'; 
$end_date  = '2009-09-05'; 
$date_from_user = '2009-08-28'; 

NOTA: Confrontando le stringhe come questo non permettono di "non valida" Date per esempio (32 dicembre) '2009-13-32' e per le stringhe formattate stranamente '2009/3/3', in modo tale che un confronto tra stringhe NON sia equivalente a un confronto di data o marca temporale. Funziona SOLO se i valori di data nelle stringhe sono in un formato CONSISTENT e CANONICAL.

EDIT aggiungere una nota qui, elaborando sull'ovvio.

Con COERENTE, voglio dire per esempio che le stringhe confrontate devono essere in formato identico: il mese deve essere sempre due personaggi, il giorno deve essere sempre due personaggi, e il carattere separatore deve essere sempre un trattino. Non possiamo confrontare in modo affidabile le "stringhe" che non sono quattro caratteri anno, due caratteri mese, due caratteri giorno. Se avessimo un mix di un carattere e due caratteri nelle stringhe, ad esempio, otterremmo un risultato inaspettato quando abbiamo confrontato, '2009-9-30' a '2009-10-11'. Vediamo umanamente "9" come inferiore a "10", ma un confronto tra stringhe vedrà '2009-9' come maggiore di '2009-1'. Non è necessario necessariamente disporre di caratteri separatori di trattini; potremmo comparare in modo altrettanto affidabile le stringhe nel formato 'YYYYMMDD'; se c'è un carattere separatore, deve essere sempre presente e sempre uguale.

Per CANONICAL, intendo che un formato che risulterà in stringhe che verranno ordinate in ordine di data. Cioè, la stringa avrà prima una rappresentazione di "anno", quindi "mese", quindi "giorno". Non possiamo confrontare in modo affidabile le stringhe nel formato 'MM-DD-YYYY', perché non è canonico.Un confronto di stringhe confrontava lo MM (mese) prima di confrontare lo YYYY (anno) dal momento che il confronto tra stringhe funziona da sinistra a destra.) Un grande vantaggio del formato di stringa 'YYYY-MM-DD' è che è canonico; le date rappresentate in questo formato possono essere confrontate in modo affidabile come stringhe.

[ADDENDUM]

Se andate per la conversione timestamp php, essere consapevole dei limiti.

Su alcune piattaforme, php non supporta i valori di data e ora precedenti al 1970-01-01 e/o successivi al 2038-01-19. (Questa è la natura del timestamp di Unix intero a 32 bit.) Le versioni successive di pf php (5.3?) Dovrebbero occuparsene.

Il fuso orario può anche essere un problema, se non si presta attenzione all'utilizzo dello stesso fuso orario durante la conversione da stringa a data/ora e da data/ora a stringa.

HTH

+1

Questo è interessante. –

+1

Sebbene senza il cast potresti incorrere in problemi se i valori di $ date_from_user, o $ start_date o $ end_date non sono date .. ie $ end_date = 'Balh Blah' ... sicuramente non funzionerà correttamente –

+0

@ spencer7593, vuoi avere dei riferimenti per questo comportamento? –

3

Nel formato che ci hai fornito, supponendo che l'utente è abbastanza intelligente per dare date valide, non è necessario per convertire in una data prima, è possibile confrontare come stringhe.

+1

A questo punto nel codice le date sono già state convalidate – meleyal

3
$start_date="17/02/2012"; 
$end_date="21/02/2012"; 
$date_from_user="19/02/2012"; 

function geraTimestamp($data) 
{ 
    $partes = explode('/', $data); 
    return mktime(0, 0, 0, $partes[1], $partes[0], $partes[2]); 
} 


$startDatedt = geraTimestamp($start_date); 
$endDatedt = geraTimestamp($end_date); 
$usrDatedt = geraTimestamp($date_from_user); 

if (($usrDatedt >= $startDatedt) && ($usrDatedt <= $endDatedt)) 
{ 
    echo "Dentro"; 
}  
else 
{ 
    echo "Fora"; 
} 
36

Utilizzare la classe DateTime se si dispone di PHP 5.3+. Più facile da usare, migliore funzionalità.

DateTime supporta internamente i fusi orari, con le altre soluzioni è a vostra disposizione per gestirlo.

<?php  
/** 
* @param DateTime $date Date that is to be checked if it falls between $startDate and $endDate 
* @param DateTime $startDate Date should be after this date to return true 
* @param DateTime $endDate Date should be before this date to return true 
* return bool 
*/ 
function isDateBetweenDates(DateTime $date, DateTime $startDate, DateTime $endDate) { 
    return $date > $startDate && $date < $endDate; 
} 

$fromUser = new DateTime("2012-03-01"); 
$startDate = new DateTime("2012-02-01 00:00:00"); 
$endDate = new DateTime("2012-04-30 23:59:59"); 

echo isDateBetweenDates($fromUser, $startDate, $endDate); 
+0

Come scrivere un test per questo codice? –

+0

Probabilmente lo trasformerai in una funzione che richiede tre parametri e restituirà un valore booleano. Dovrebbe essere molto facile da testare? – oldwizard

+0

Direi che la funzione dovrebbe restituire true per '2012-02-01' è tra' 2012-02-01 ... 2014-04-30 23: 59: 59'. –

1

Si può provare questo:

//custom date for example 
$d1 = new DateTime("2012-07-08"); 
$d2 = new DateTime("2012-07-11"); 
$d3 = new DateTime("2012-07-08"); 
$d4 = new DateTime("2012-07-15"); 

//create a date period object 
$interval = new DateInterval('P1D'); 
$daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2)); 
$daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4)); 
array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange); 
+1

nota di versione: 'iterator_to_array()' è disponibile da PHP 5.1 – Raptor

0

Ho trovato questo metodo il più facile:

$start_date = '2009-06-17'; 
$end_date = '2009-09-05'; 
$date_from_user = '2009-08-28'; 

$start_date = date_create($start_date); 
$date_from_user = date_create($date_from_user); 
$end_date = date_create($end_date); 

$interval1 = date_diff($start_date, $date_from_user); 
$interval2 = date_diff($end_date, $date_from_user); 

if($interval1->invert == 0){ 
    if($interval2->invert == 1){ 

    // if it lies between start date and end date execute this code 

    } 
} 
Problemi correlati