Как сравнить два объекта DateTime в PHP 5.2.8?

294

Взглянув на документацию по PHP, следующие два метода DateTimeобъекта могут решить мою проблему:

  • DateTime :: diff : Получите разницу и используйте ее, чтобы определить, что является более древним.
  • DateTime :: getTimestamp : получить метку времени UNIX и сравнить ее.

Оба эти метода отмечены в документе как доступные в версии> = 5.3 (и, что неудивительно, если я попытаюсь вызвать их, я обнаружу, что они не существуют). Я не могу найти какую-либо конкретную документацию для 5.2.8, поэтому я не уверен, есть ли в моей версии эквивалентные методы. Я гуглил проблему и нашел эклектичный ряд решений, ни одно из которых не отвечает моим очень простым требованиям:

  • Как сравнить два объекта DateTime?
  • Где я могу найти документацию для предыдущих версий PHP? Конкретно версия 5.2.8?

Для некоторого контекста у меня есть следующий код:

$st_dt = new DateTime(verifyParam ('start_date'));
$end_dt = new DateTime(verifyParam ('end_date'));

// is the end date more ancient than the start date?
if ($end_dt < $start_dt) 

Видимо, на этом парне нет оператора сравнения.

редактировать

Очевидно, мои предположения были полностью ложными (спасибо Милен за столь эффективную иллюстрацию). Есть оператор сравнения, и он работает просто отлично, спасибо. Иногда я действительно скучаю по компилятору. Ошибка в приведенном выше коде, я уверен, вы найдете ее намного быстрее, чем я :).

RedBlueThing
источник
1
Что касается отсутствия компилятора - установите «error_reporting» на «E_ALL», и вы получите уведомления, такие как «Notice: Undefined variable: start_dt in ...».
Милен А. Радев
5
Также, пожалуйста, используйте htmlentities на своих $_POSTварах, иначе котенка убьют.
Клемент Херреман
2
А где ошибка? : p, я тоже это делаю U_U. Заранее спасибо!
Castarco
2
@castarco Я инициализирую $ st_dt, но сравниваю с неинициализированным $ start_dt. Проверьте имена переменных и, возможно, следуйте предложению Милена и установите error_reporting на E_ALL, чтобы получить неопределенные предупреждения о переменных. :)
RedBlueThing

Ответы:

432

Следующее, кажется, подтверждает, что есть операторы сравнения для класса DateTime:

dev:~# php
<?php
date_default_timezone_set('Europe/London');

$d1 = new DateTime('2008-08-03 14:52:10');
$d2 = new DateTime('2008-01-03 11:11:10');
var_dump($d1 == $d2);
var_dump($d1 > $d2);
var_dump($d1 < $d2);
?>
bool(false)
bool(true)
bool(false)
dev:~# php -v
PHP 5.2.6-1+lenny3 with Suhosin-Patch 0.9.6.2 (cli) (built: Apr 26 2009 20:09:03)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
dev:~#
Милен А. Радев
источник
7
Спасибо, Милен, похоже, мне просто нужно было удалить мои ложные предположения, и внезапно для меня стала очевидна явная ошибка в моем коде.
RedBlueThing
2
Хм, это интересно. Возможно, в какой-то момент мы сможем перегрузить операторы в пользовательских классах.
Ionuț G. Stan
1
От php.net/manual/en/language.operators.comparison.php Встроенные классы могут определять свое собственное сравнение, разные классы не сравнимы, один класс - сравнивать свойства так же, как массивы (PHP 4), PHP 5 имеет свои собственное объяснение
Сол
7
будьте внимательны, сравнивая дату
1
TiMESPLiNTER, я считаю, что предупреждение состоит в том, что если вас интересует только сравнение дат, вы можете упустить из виду тот факт, что часы разные, и, следовательно, два значения DateTimeс одной и той же датой не будут сравниваться как равные, если вы считаете, что они должны это делать. Вы можете исправить это, явно установив временные компоненты объекта на ноль, прежде чем сравнивать их.
Джейсон
52

Из официальной документации :

Начиная с PHP 5.2.2, объекты DateTime можно сравнивать с помощью операторов сравнения .

$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2); // false
var_dump($date1 < $date2); // true
var_dump($date1 > $date2); // false

Для версий PHP до 5.2.2 (фактически для любой версии) вы можете использовать diff .

$datetime1 = new DateTime('2009-10-11'); // 11 October 2013
$datetime2 = new DateTime('2009-10-13'); // 13 October 2013

$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days'); // +2 days
Роберто Алонсо
источник
3
Я считаю этот ответ лучшим, поскольку он цитирует руководство, а не просто проверяет поведение и предполагает, что результат соответствует ожидаемому. Так что это не место для догадок. Браво Роберто.
cprn
3
@roberto DateTime :: diff был добавлен только в PHP 5.3
NeXuS
30

Вы также можете сравнить секунды эпохи:

$d1->format('U') < $d2->format('U')

Источник: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (довольно интересная статья о DateTime)

Julien
источник
16
Остерегайтесь, что formatпроизводит строку , так что это сравнение строк. Это едва проблема после 1000000000 эпох (примерно 9 сентября 2001 года), но если вам придется иметь дело с датами до этого, вы можете столкнуться с проблемами из-за разной длины номеров. Либо конвертируйте результаты в числа (вычитание их тоже работает), либо используйте действительно сортируемый формат вроде c.
MaxArt
1
@MaxArt, не могли бы вы рассказать о проблемах из-за разной длины строк? Руководство, касающееся строк в числовом контексте: «Если строка не содержит символов«. »,« E »или« E », а числовое значение соответствует ограничениям целочисленного типа (как определено в PHP_INT_MAX), строка будет оцениваться как целое число. Во всех остальных случаях оно будет оцениваться как число с плавающей точкой. " Будущие даты (около 2038 года) могут переполнить 32-разрядные целые числа со знаком, но в чем проблема с более старыми датами?
Адриан Гюнтер,
1
@ AdrianGünter Проблема в том, что мы не будем в числовом контексте, но мы будем иметь дело со строками . Числовые, но все же строки. Таким образом, сравнение строк будет сделано.
МаксАрт
2
@ FrédéricMarchal Да, позже я действительно узнал, что мой предыдущий комментарий фактически неверен. У PHP есть действительно злой способ справиться с этими случаями, никакой другой язык (насколько я знаю) не приводит к числам, когда у вас есть две строки для сравнения. Это действительно испортит ваш код, если вы действительно хотите сделать лексикографическое сравнение.
MaxArt
20

Если вы хотите сравнить даты, а не время, вы можете использовать это:

$d1->format("Y-m-d") == $d2->format("Y-m-d")
блаблабла
источник
5
Вы также можете установить время сброса. $d1->setTime(0, 0, 0);
Атлан
3

Начиная с PHP 7.x, вы можете использовать следующее:

$aDate = new \DateTime('@'.(time()));
$bDate = new \DateTime('@'.(time() - 3600));

$aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate`
jens1o
источник
0
$elapsed = '2592000';
// Time in the past
$time_past = '2014-07-16 11:35:33';
$time_past = strtotime($time_past);

// Add a month to that time
$time_past = $time_past + $elapsed;

// Time NOW
$time_now = time();

// Check if its been a month since time past
if($time_past > $time_now){
    echo 'Hasnt been a month';    
}else{
    echo 'Been longer than a month';
}
Кайл Кутс
источник
временная метка имеет некоторые ограничения, вы можете прочитать этот stackoverflow.com/a/7229760/2652018
Steel Brain
Приятно знать! Это было просто для простого сравнения времени.
Кайл Кутс
-1

Это может помочь вам.

$today = date("m-d-Y H:i:s");
$thisMonth =date("m");
$thisYear = date("y");
$expectedDate = ($thisMonth+1)."-08-$thisYear 23:58:00";


if (strtotime($expectedDate) > strtotime($today)) {
    echo "Expected date is greater then current date";
    return ;
} else
{
 echo "Expected date is lesser then current date";
}
Тарун Гупта
источник
временная метка имеет некоторые ограничения, вы можете прочитать этот stackoverflow.com/a/7229760/2652018
Steel Brain
@SteelBrain Вы думаете, что ограничение временной отметки беспокоит вышеуказанный код, который имеет все текущее время, пожалуйста, прочитайте код еще раз. В основном, он проверяет парня $ Ожидаемая дата, которая всегда будет в текущем месяце. Я не думаю, что мы должны думать об ограничении отметки времени здесь в этом случае.
Тарун Гупта
Я знаю, но это не рекомендуемый способ, (я не понизил голосование :-))
Steel Brain
Можете ли вы предложить рекомендуемый способ.
Тарун Гупта
конечно, $today = new DateTime("now"); $time = DateTime::createFromFormat('d-m-Y',"26-October-1998"); if ($today > $time){echo "today is greater";}else{echo "other time is greater";}ура
Steel Brain