PHP 5.2.8で2つのDateTimeオブジェクトを比較するにはどうすればよいですか?


294

PHPのドキュメントを見ると、DateTimeオブジェクトの次の2つのメソッドはどちらも私の問題を解決するようです。

これらのメソッドは両方とも、バージョン5.3以降で利用可能であるとdocoでマークされています(そして、当然のことながら、それらを呼び出そうとすると、それらが存在しないことがわかります)。5.2.8の特定のドキュメントが見つからないため、私のバージョンに同等のメソッドがあるかどうかわかりません。私は問題をグーグル検索し、折衷的な範囲の解決策を見つけましたが、どれも私の非常に単純な要件に答えません:

  • 2つのDateTimeオブジェクトを比較するにはどうすればよいですか?
  • 以前のバージョンのPHPのdocoはどこにありますか?特にバージョン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) 

どうやらこの男には比較演算子がありません。

編集する

どうやら私の仮定は完全に誤りでした(これを効果的に説明してくれたMilenに感謝します)。比較演算子があり、うまく動作します。時々私は本当にコンパイラーが恋しいです。バグは上のコードにありますが、私が思ったよりもずっと早く見つけることができると思います:)


1
コンパイラーの欠如について-「error_reporting」を「E_ALL」に設定すると、「通知:未定義の変数:start_dt in ...」のような通知が表示されます。
Milen A. Radev

5
また、$_POSTvarにhtmlentityを使用してください。そうしないと、子猫が殺されます。
Clement Herreman、2010

2
そしてエラーはどこですか?:p、私もやっているU_U。前もって感謝します!
castarco

2
@castarco $ st_dtを初期化しますが、初期化されていない$ start_dtと比較します。変数名を確認し、Milenの提案に従い、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
Milenに感謝します。誤った仮定を削除する必要があったようですが、突然コード内の目立ったバグが明らかになりました。
RedBlueThing 2009年

2
うーん、これは面白いです。たぶん、ある時点で、ユーザー定義クラスの演算子をオーバーロードできるようになるでしょう。
Ionuț G. Stan

1
php.net/manual/en/language.operators.comparison.phpから組み込みクラスは独自の比較を定義できます。異なるクラスは比較できません。同じクラスです。配列と同じようにプロパティを比較します(PHP 4)。PHP5には、自分の説明
ソール

7
時が設定されていない日時と設定された日時を比較する場合(デフォルトのコンストラクタ)
max4ever

1
TiMESPLiNTER、私は警告が、日付を比較することにのみ関心がある場合、時間は異なるという事実を見落とす可能性があるためDateTime、同じ日付の2つのは等しいと比較されないはずであると信じていると思います。これを修正するには、オブジェクトの時間コンポーネントを比較する前に明示的にゼロに設定します。
Jason

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

5.2.2より前のPHPバージョン(実際にはすべてのバージョン)では、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
この答えは、動作をチェックして結果が期待どおりであると想定するのではなく、マニュアルを引用しているので、最もよくわかります。SOは当て推量の場所ではありません。ブラボーロベルト。
cprn 2016

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に関するかなり興味深い記事)


16
文字列format生成することに注意してください。これは文字列の比較です。これは1000000000エポックタイム(大体2001年9月9日)以降はほとんど問題になりませんが、それより前の日付を処理する必要がある場合、数値の長さが異なるために問題が発生する可能性があります。結果を数値に変換する(減算も機能する)か、などの本当にソート可能な形式を使用します。c
MaxArt、2015年

1
@MaxArtは、異なる文字列の長さによる問題について詳しく説明してもらえますか?数値コンテキストの文字列に関するマニュアル:「文字列に文字 '。'、 'e'、または 'E'が含まれておらず、数値が整数型の制限(PHP_INT_MAXで定義)に適合している場合、文字列は整数として評価されます。それ以外の場合はすべて、浮動小数点として評価されます。」将来の日付(2038年前後)は符号付き32ビット整数をオーバーフローする可能性がありますが、古い日付の問題は何ですか?
AdrianGünter15年

1
@AdrianGünter問題は、数値のコンテキストではないということですが、文字列を扱います。数値ですが、まだ文字列です。したがって、文字列の比較が行われます。
MaxArt


2
@FrédéricMarchalはい、確かに後で私は私の以前のコメントが実際に偽であることを後で学びました。PHPはこれらのケースを処理するために本当に邪魔な方法を持っています。比較する2つの文字列がある場合、他の言語(私の知る限り)は数値にキャストしません。辞書式の比較を実際に行いたい場合は、コードが本当に失敗します。
MaxArt 2016

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`

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

知っておくといい!これは単に時間を比較する簡単な方法のために意図されただけです。
カイルクーツ2014

-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は、現在の日付時刻をすべて含む上記のコードのタイムスタンプ制限が気になると思いますか?コードをもう一度読んでください。基本的に、常に現在の月にある$ expectedDateをチェックします。この場合、タイムスタンプの制限について考える必要があるとは思いません。
Tarun Gupta 2014

(私はdownvoteしませんでした:-))、私は知っているが、それは推奨される方法ではありません
スチールブレイン

おすすめの方法を提案していただけますか。
Tarun Gupta 2014

確かに、$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";}乾杯。
鋼の脳
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.