web-dev-qa-db-fra.com

Comment vérifier si une date est dans une plage donnée?

Si tu as un $start_date et $end_date, comment pouvez-vous vérifier si une date donnée par l'utilisateur se situe dans cette plage?

par exemple.

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28'; 

Pour le moment, les dates sont-elles des chaînes? Cela aiderait-il de les convertir en entiers timestamp?

74
meleyal

Les convertir en horodatages est la meilleure solution, en utilisant strtotime , par exemple.

$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));
}
110
ConroyP

Il n'est pas nécessaire de convertir en horodatage pour effectuer la comparaison, étant donné que les chaînes sont validées en tant que dates au format canonique 'AAAA-MM-JJ'.

Ce test fonctionnera:

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

donné:

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

REMARQUE: La comparaison de chaînes comme celle-ci permet des dates "non valides", par exemple. (32 décembre) '2009-13-32' et pour les chaînes étrangement formatées '2009/3/3', de sorte qu'une comparaison de chaîne NE sera PAS équivalente à une comparaison de date ou d'horodatage. Cela fonctionne UNIQUEMENT si les valeurs de date dans les chaînes sont dans un COHÉRENT et CANONIQUE format.

EDIT pour ajouter une note ici, développant l'évidence.

Par COHÉRENT , je veux dire par exemple que les chaînes comparées doivent être au format identique: le mois doit toujours être de deux caractères, le jour doit toujours être de deux caractères et le caractère séparateur doit toujours être un tiret. Nous ne pouvons pas comparer de manière fiable des "chaînes" qui ne sont pas composées d'une année à quatre, d'un mois de caractère ou d'un jour de deux caractères. Si nous avions un mélange de caractère et deux mois de caractère dans les chaînes, par exemple, nous obtiendrions un résultat inattendu lors de la comparaison, '2009-9-30' à '2009-10-11'. Nous voyons humainement "9" comme étant inférieur à "10", mais une comparaison de chaînes verra '2009-9' plus grand que '2009-1'. Nous n'avons pas nécessairement besoin d'un séparateur de tirets; nous pourrions tout aussi bien comparer les chaînes dans 'YYYYMMDD' format; s'il y a un caractère séparateur, il doit toujours être là et toujours le même.

Par CANONIQUE , je veux dire un format qui aboutira à des chaînes qui seront triées par ordre de date. C'est-à-dire que la chaîne aura une représentation de "année" en premier, puis "mois", puis "jour". Nous ne pouvons pas comparer de manière fiable les chaînes dans 'MM-DD-YYYY' format, parce que ce n'est pas canonique. Une comparaison de chaînes comparerait le MM (mois) avant de comparer YYYY (année) car la comparaison de chaînes fonctionne de gauche à droite.) Un gros avantage de "AAAA-MM-JJ" Le format de chaîne est qu'il est canonique; les dates représentées dans ce format peuvent être comparées de manière fiable en tant que chaînes.

[ADDENDA]

Si vous optez pour la conversion php timestamp, soyez conscient des limitations.

Sur certaines plates-formes, php ne prend pas en charge les valeurs d’horodatage antérieures à 1970-01-01 et/ou ultérieures à 2038-01-19. (C'est la nature de l'entier 32 bits de l'horodatage Unix.) Les versions ultérieures pf php (5.3?) Sont supposées résoudre ce problème.

Le fuseau horaire peut également être un problème si vous ne prenez pas soin d'utiliser le même fuseau horaire lors de la conversion de chaîne en horodatage et de timestamp en chaîne.

HTH

46
spencer7593

Utilisez la classe DateTime si vous avez PHP 5.3+. Plus facile à utiliser, meilleures fonctionnalités.

DateTime prend en charge les fuseaux horaires en interne, avec les autres solutions, à vous de le gérer.

<?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);
41
oldwizard
$startDatedt = strtotime($start_date)
$endDatedt = strtotime($end_date)
$usrDatedt = strtotime($date_from_user)

if( $usrDatedt >= $startDatedt && $usrDatedt <= $endDatedt)
{
   //..falls within range
}
4
Stan R.

Convertissez les deux dates en horodatages puis faites

pseudocode:

if date_from_user > start_date && date_from_user < end_date
    return true
3
Glen

Dans le format que vous avez fourni, en supposant que l'utilisateur soit suffisamment intelligent pour vous donner des dates valides, vous n'avez pas besoin de convertir d'abord une date, vous pouvez les comparer sous forme de chaînes.

3
richardtallent
$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";
}
3
Paulo Henrique

Convertissez-les en entiers de dates ou d'horodatages, puis vérifiez que $ date_from_user est <= $ end_date et> = $ start_date

2
TheTXI

Vous pouvez essayer ceci:

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

J'ai trouvé cette méthode la plus simple:

$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

  }
}
0
iniravpatel