Как проверить, находится ли дата в заданном диапазоне? - PullRequest
73 голосов
/ 10 июня 2009

Если у вас есть $start_date и $end_date, как вы можете проверить, попадает ли указанная пользователем дата в этот диапазон?

, например

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28'; 

На данный момент даты являются строками, поможет ли их преобразовать в целые числа с метками времени?

Ответы [ 10 ]

110 голосов
/ 10 июня 2009

Преобразование их в временные метки - это способ работать хорошо, используя strtotime , например,

$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));
}
46 голосов
/ 10 июня 2009

Нет необходимости преобразовывать в метку времени для сравнения, поскольку строки проверяются как даты в каноническом формате «ГГГГ-ММ-ДД».

Этот тест будет работать:

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

Дано:

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

ПРИМЕЧАНИЕ. Сравнение строк, подобных этой, допускает «недействительные» даты, например (32 декабря) «2009-13-32» и для странно отформатированных строк «2009/3/3», так что сравнение строк НЕ будет эквивалентно сравнению даты или времени. Это работает ТОЛЬКО, если значения даты в строках имеют формат CONSISTENT и CANONICAL .

РЕДАКТИРОВАТЬ , чтобы добавить сюда примечание, уточняя очевидное.

Под CONSISTENT я имею в виду, например, что сравниваемые строки должны быть в одинаковом формате: месяц всегда должен быть двумя символами, день всегда должен быть двумя символами, а символ разделителя всегда должен быть тире. Мы не можем достоверно сравнить «строки», которые не состоят из четырех символов года, двух символов месяца, двух символов дня. Например, если бы в строках было сочетание одного символа и двух символьных месяцев, мы получили бы неожиданный результат при сравнении '2009-9-30' с '2009-10-11'. Мы по-человечески видим, что «9» меньше, чем «10», но при сравнении строк мы увидим '2009-9' больше, чем '2009-1'. Нам не обязательно иметь символы разделителя тире; мы могли бы так же надежно сравнить строки в формате 'YYYYMMDD'; если есть символ разделителя, он всегда должен быть там и всегда быть одним и тем же.

Под CANONICAL я имею в виду формат, в результате которого будут отсортированы строки, отсортированные по дате. То есть строка будет сначала иметь представление «год», затем «месяц», затем «день». Мы не можем надежно сравнивать строки в формате 'MM-DD-YYYY', потому что это не канонично. Сравнение строк будет сравнивать MM (месяц) до сравнения YYYY (год), поскольку сравнение строк выполняется слева направо.) Большим преимуществом формата строки «ГГГГ-ММ-ДД» является то, что каноническое; даты, представленные в этом формате, можно надежно сравнивать как строки.

[ДОБАВЛЕНИЕ]

Если вы действительно хотите преобразовать метку времени в php, помните об ограничениях.

На некоторых платформах php не поддерживает значения меток времени ранее 1970-01-01 и / или позже 2038-01-19. (Такова природа 32-разрядного целого числа с меткой времени в Unix.) Предполагается, что более поздние версии pf php (5.3?) Решат эту проблему.

Часовой пояс также может быть проблемой, если вы не будете осторожны в использовании одного и того же часового пояса при преобразовании строки в метку времени и из метки времени обратно в строку.

НТН

41 голосов
/ 30 января 2012

Используйте класс DateTime, если у вас PHP 5.3+. Легче в использовании, лучшая функциональность.

DateTime внутренне поддерживает часовые пояса, а другие решения решать вам.

<?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);
4 голосов
/ 10 июня 2009
$startDatedt = strtotime($start_date)
$endDatedt = strtotime($end_date)
$usrDatedt = strtotime($date_from_user)

if( $usrDatedt >= $startDatedt && $usrDatedt <= $endDatedt)
{
   //..falls within range
}
3 голосов
/ 18 декабря 2011
$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 голосов
/ 10 июня 2009

В указанном вами формате, если пользователь достаточно умен, чтобы указать правильные даты, вам не нужно сначала преобразовывать дату, вы можете сравнить их как строки.

3 голосов
/ 10 июня 2009

Преобразуйте обе даты в метки времени, затем выполните

псевдокод:

if date_from_user > start_date && date_from_user < end_date
    return true
2 голосов
/ 10 июня 2009

Преобразуйте их в целые числа дат или отметки времени, а затем просто проверьте, что $ date_from_user <= $ end_date и> = $ start_date

1 голос
/ 25 марта 2014

Вы можете попробовать это:

//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);
0 голосов
/ 20 июня 2016

Я нашел этот метод самым простым:

$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

  }
}
...