2009-06-10 21 views
64

Si tiene un $start_date y $end_date, ¿cómo puede verificar si una fecha dada por el usuario se encuentra dentro de ese rango?¿Cómo verificar si una fecha está en un rango determinado?

p. Ej.

$start_date = '2009-06-17'; 

$end_date = '2009-09-05'; 

$date_from_user = '2009-08-28'; 

Por el momento, las fechas son cadenas, ¿sería útil convertirlas en enteros de marca de tiempo?

+0

Sería de gran ayuda, entonces tendría acceso a las funciones de manipulación de la fecha existen. – ChrisF

+3

Solo tenga en cuenta la limitación de la marca de tiempo ya que las marcas de tiempo Unix comienzan en la época, que es el 1 de enero de 1970 (1970-01-01), por lo que podría tener un comportamiento extraño para las fechas de prueba antes de 1970. –

+1

@Shadi Usted sabe que existe Números NEGATIVOS, ¿verdad? –

Respuesta

96

Convirtiéndolos en marcas de tiempo es la manera de hacerlo bien, usando strtotime, por ejemplo

$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

convertirlos en fechas o números enteros de fecha y hora y luego solo cheque de $ date_from_user se < = $ fecha_final y> = $ fecha_inicial

+3

¿Podría aclarar 'conviértalos en fechas'? ¿Cómo lo harías tú? ¿Pensé que PHP no tiene fecha tipo? – meleyal

3

Conversor ambas fechas a las marcas de tiempo y luego hacer

pseudocódigo:

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

Es posible que desee editarlo para que también incluya start_date y end_date en el rango. En este momento si date_from_user es igual a cualquiera, no se contará. – TheTXI

+0

El OP no especificó rangos inclusivos o exclusivos, por lo que les dejaré elegir qué estrategia usar – Glen

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

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

que no incluirá ninguna coincidencia exacta con la fecha de inicio o finalización – TheTXI

+0

thx. error de tipografía. arreglé el código –

+0

OP no solicitó coincidencias inclusivas. –

46

No es necesario convertir a marca de tiempo para hacer la comparación, ya que las cadenas se validan como las fechas en formato canónico 'AAAA-MM-DD'.

Esta prueba va a funcionar:

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

dadas:

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

NOTA: La comparación de cadenas como éste sí permite "no válido", por ejemplo, las fechas (32 de diciembre) '2009-13-32' y para cadenas extrañamente formateadas '2009/3/3', de modo que una comparación de cadenas NO será equivalente a una comparación de fecha o marca de tiempo. Esto funciona SÓLO si los valores de fecha en las cadenas están en un formato CONSISTENT y CANONICAL.

EDIT para agregar una nota aquí, explicando lo obvio.

Por CONSISTENTE, me refiero, por ejemplo, que las cadenas se comparan deben estar en formato idéntico: el mes debe ser siempre dos caracteres, el día debe ser siempre dos caracteres, y el carácter separador debe ser siempre un guión. No podemos comparar confiablemente "cadenas" que no sean de cuatro caracteres anuales, dos caracteres mensuales, dos caracteres diarios. Si tuviéramos una combinación de un carácter y dos meses de carácter en las cuerdas, por ejemplo, obtendríamos resultados inesperados cuando comparamos, '2009-9-30' con '2009-10-11'. Humanamente vemos "9" como menos de "10", pero una comparación de cadenas verá '2009-9' como mayor que '2009-1'. No necesariamente necesitamos tener un separador de guiones; podríamos comparar cadenas de manera confiable en el formato 'YYYYMMDD'; si hay un carácter separador, tiene que estar siempre allí y ser siempre el mismo.

Por CANÓNICA, quiero decir que un formato que dará lugar a cadenas que se ordenarán por orden de fecha. Es decir, la cadena tendrá una representación de "año" primero, luego "mes", luego "día". No podemos comparar cadenas confiablemente en el formato 'MM-DD-YYYY', porque eso no es canónico.Una comparación de cadenas compararía el MM (mes) antes de comparar YYYY (año) ya que la comparación de cadenas funciona de izquierda a derecha.) Una gran ventaja del formato de cadena 'YYYY-MM-DD' es que es canónico; las fechas representadas en este formato se pueden comparar confiablemente como cadenas.

[ANEXO]

Si tienes que ir por la conversión de marca de tiempo php, ser conscientes de las limitaciones.

En algunas plataformas, php no admite valores de marca de tiempo anteriores a 1970-01-01 y posteriores a 2038-01-19. (Esa es la naturaleza del entero de 32 bits de la marca de tiempo Unix.) Se supone que las versiones posteriores pf php (5.3?) Abordan eso.

La zona horaria también puede ser un problema, si no tiene cuidado de utilizar la misma zona horaria al convertir de cadena a marca de tiempo y de marca de hora a cadena.

HTH

+1

Este es interesante. –

+1

Aunque sin conversión, podría tener problemas si los valores de $ date_from_user, o $ start_date, o $ end_date no son fechas ... es decir $ end_date = 'Balh Blah' ... definitivamente no funcionarán correctamente –

+0

@ spencer7593, ¿verdad? tener algunas referencias para este comportamiento? –

3

En el formato que ha proporcionado, suponiendo que el usuario es lo suficientemente inteligente como para darle fechas válidas, que no es necesario para convertir a una fecha en primer lugar, se puede comparar como cadenas.

+1

En este punto del código, las fechas ya se han validado – 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

Utilice la clase DateTime si tiene PHP 5.3+. Más fácil de usar, mejor funcionalidad.

DateTime admite internamente zonas horarias, con las otras soluciones depende de usted manejar eso.

<?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

¿Cómo escribir una prueba para este código? –

+0

Probablemente transformaría esto en una función que toma tres parámetros y devuelve un booleano. Debería ser muy fácil de probar? – oldwizard

+0

Diría que la función debería ser verdadera para '2012-02-01' entre' 2012-02-01 ... 2014-04-30 23: 59: 59'. –

1

Puede probar esto:

//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

version note: 'iterator_to_array()' está disponible desde PHP 5.1 – Raptor

0

me encontré con este método el más fácil:

$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 

    } 
} 
Cuestiones relacionadas