Como eu comparo dois objetos DateTime no PHP 5.2.8?


294

Examinando a documentação do PHP, os dois métodos a seguir do DateTimeobjeto parecem resolver o meu problema:

Ambos os métodos estão marcados no documento como disponíveis na versão> = 5.3 (e, não surpreendentemente, se eu tentar chamá-los, acho que eles não existem). Não consigo encontrar nenhuma documentação específica para o 5.2.8, portanto, não tenho certeza se existem métodos equivalentes na minha versão. Eu pesquisei o problema e encontrou uma gama eclética de soluções, nenhuma das quais responder às minhas exigências muito simples:

  • Como eu comparo dois objetos DateTime?
  • Onde posso encontrar o documento para versões anteriores do PHP? Especificamente versão 5.2.8?

Para algum contexto, eu tenho o seguinte código:

$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) 

Aparentemente, não há operador de comparação nesse cara.

Editar

Aparentemente, minhas suposições eram completamente falsas (obrigado Milen por ilustrar isso com tanta eficácia). Existe um operador de comparação e funciona muito bem, obrigado. Às vezes, sinto muita falta de um compilador. O bug está no código acima, tenho certeza que você o encontrará muito mais rápido do que eu :).


1
Com relação à falta de compilador - defina "error_reporting" como "E_ALL" e você receberá avisos como "Aviso: Variável indefinida: start_dt in ...".
Milen A. Radev

5
Além disso, use htmlentities em seus $_POSTvars, ou o gatinho será morto.
Clement Herreman

2
E onde está o erro? : p, eu também estou fazendo isso U_U. Desde já, obrigado!
Castarco 8/11

2
@castarco Inicializo $ st_dt, mas comparo com um $ start_dt não inicializado. Verifique seus nomes de variáveis ​​e talvez siga a sugestão de Milen e defina error_reporting como E_ALL para obter avisos de variáveis ​​indefinidos. :)
RedBlueThing

Respostas:


432

O seguinte parece confirmar que existem operadores de comparação para a classe 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
Obrigado Milen, parece que eu só precisava remover minhas falsas suposições e de repente o bug flagrante no meu código se tornou óbvio para mim.
RedBlueThing

2
Hmm, isso é interessante. Talvez em algum momento possamos sobrecarregar os operadores em classes definidas pelo usuário.
Ionuţ G. Stan

1
Em php.net/manual/en/language.operators.comparison.php As classes internas podem definir sua própria comparação, diferentes classes são incomparáveis, mesma classe - compare as propriedades da mesma maneira que as matrizes (PHP 4), o PHP 5 tem seu própria explicação
Saul

7
cuidado ao comparar uma data e hora sem hora marcada e um com ele definido (construtor padrão)
max4ever

1
Por outro lado, acredito que o aviso é que, se você estiver interessado apenas em comparar datas, poderá ignorar o fato de que as horas são diferentes e, portanto, dois DateTimesegundos com a mesma data não serão comparados como iguais quando você acredita que deveriam. Você pode remediar isso definindo explicitamente os componentes de tempo do objeto como zero antes de compará-los.
Jason

52

A partir da documentação oficial :

A partir do PHP 5.2.2, os objetos DateTime podem ser comparados usando operadores de comparação .

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

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

Para versões do PHP anteriores à 5.2.2 (na verdade, para qualquer versão), você pode usar o 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
Acho melhor essa resposta, pois cita o manual em vez de apenas verificar o comportamento e assumir que o resultado é o esperado. SO não é um lugar para adivinhações. Bravo Roberto.
CPRN

3
@roberto datetime :: dif só foi adicionado em PHP 5.3
NeXuS

30

Você também pode comparar os segundos da época:

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

Fonte: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (artigo bastante interessante sobre o DateTime)


16
Cuidado que formatproduz uma string , então essa é uma comparação de strings. É um problema após o período de 1000000000 (aproximadamente 9 de setembro de 2001), mas se você precisar lidar com datas anteriores , poderá ocorrer problemas devido a diferentes comprimentos de números. Converta os resultados em números (subtrai-los também funciona) ou use um formato verdadeiramente classificável como c.
maxart

1
@ MaxArt, você poderia explicar os problemas devido a diferentes comprimentos de string? O manual, referente a cadeias de caracteres em contextos numéricos: "Se a cadeia de caracteres não contiver nenhum dos caracteres '.', 'E' ou 'E' e o valor numérico se enquadrar nos limites do tipo inteiro (conforme definido por PHP_INT_MAX), a cadeia de caracteres será avaliado como um número inteiro. Em todos os outros casos, será avaliado como um número flutuante ". Datas futuras (por volta de 2038) podem estourar números inteiros de 32 bits assinados, mas qual é o problema com datas mais antigas?
Adrian Günter

1
@ AdrianGünter O problema é que não estaríamos em um contexto numérico, mas lidaríamos com strings . Numérico, mas ainda seqüências de caracteres. Portanto, uma comparação de string seria feita.
MaxArt 16/09/2015


2
@ FrédéricMarchal Sim, eu aprendi mais tarde que meu comentário anterior é de fato falso. O PHP tem uma maneira muito maliciosa de tratar esses casos; nenhuma outra linguagem (como eu sei) transmite números quando você tem duas cadeias para comparar. Realmente estraga seu código se você realmente deseja fazer uma comparação lexicográfica.
MaxArt #

20

Se você deseja comparar datas e não horas, você pode usar o seguinte:

$d1->format("Y-m-d") == $d2->format("Y-m-d")

5
Você também pode definir o tempo de redefinição. $d1->setTime(0, 0, 0);
Athlan

3

No PHP 7.x, você pode usar o seguinte:

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

$aDate <=> $bDate; // => 1, `$aDate` is newer than `$bDate`

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';
}

timestamp tem algumas limitações, convém ler este stackoverflow.com/a/7229760/2652018
Steel Brain

Bom saber! Isso foi feito apenas para uma maneira simples de comparar os tempos.
Kyle galeirões

-1

Isso pode ajudá-lo.

$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";
}

timestamp tem algumas limitações, convém ler este stackoverflow.com/a/7229760/2652018
Steel Brain

@SteelBrain você acha que a limitação de carimbo de data / hora incomoda acima do código que está com todo o horário atual? Por favor, leia o código novamente. Eu acho que não devemos pensar na limitação de carimbo de data e hora aqui neste caso.
Tarun Gupta

Eu sei, mas não é um meio recomendado, (eu não downvote :-))
Aço Cérebro

Você pode sugerir uma maneira recomendada.
Tarun Gupta

claro, $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";}brinde.
Steel Brain
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.