ฉันจะเปรียบเทียบสองวัตถุ DateTime ใน PHP 5.2.8 ได้อย่างไร


294

เมื่อดูเอกสาร PHP แล้วทั้งสองวิธีต่อไปนี้ของDateTimeวัตถุจะแก้ปัญหาของฉันได้:

  • DateTime :: diff : รับความแตกต่างและใช้สิ่งนั้นเพื่อพิจารณาว่าอันไหนโบราณกว่ากัน
  • DateTime :: getTimestamp : รับเวลา UNIX และเปรียบเทียบสิ่งเหล่านั้น

ทั้งสองวิธีเหล่านี้มีการทำเครื่องหมายในdocoว่ามีให้ในเวอร์ชัน> = 5.3 (และไม่น่าแปลกใจถ้าฉันพยายามโทรหาพวกเขาฉันพบว่าพวกเขาไม่มีอยู่จริง) ฉันไม่พบเอกสารเฉพาะสำหรับ 5.2.8 ดังนั้นฉันไม่แน่ใจว่ามีวิธีเทียบเท่าในรุ่นของฉันหรือไม่ ฉันได้Googledปัญหาและพบวิธีการแก้ปัญหาที่หลากหลายซึ่งไม่มีคำตอบใดที่ฉันต้องการได้ง่าย:

  • ฉันจะเปรียบเทียบวัตถุ DateTime สองรายการได้อย่างไร
  • ฉันจะหา doco สำหรับ 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) 

เห็นได้ชัดว่าไม่มีผู้ดำเนินการเปรียบเทียบกับผู้ชายคนนี้

แก้ไข

เห็นได้ชัดว่าสมมติฐานของฉันเป็นเท็จอย่างสมบูรณ์ (ขอบคุณ Milen สำหรับการอธิบายอย่างมีประสิทธิภาพ) มีโอเปอเรเตอร์เปรียบเทียบและใช้งานได้ดีขอบคุณ บางครั้งฉันก็คิดถึงคอมไพเลอร์ ข้อผิดพลาดอยู่ในรหัสด้านบนฉันแน่ใจว่าคุณจะพบมันเร็วกว่าที่ฉันทำ :)


1
เกี่ยวกับการขาดคอมไพเลอร์ - ตั้งค่า "error_reporting" เป็น "E_ALL" และคุณจะได้รับการแจ้งเตือนเช่น "ประกาศ: ตัวแปรที่ไม่ได้กำหนด: start_dt ใน ... "
Milen A. Radev

5
นอกจากนี้โปรดใช้ htmlentities บน$_POSTvars ของคุณมิเช่นนั้นลูกแมวจะถูกฆ่า
Clere Herreman

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

2
อืมมันน่าสนใจนะ บางทีในบางครั้งเราอาจโอเวอร์โหลดโอเปอเรเตอร์ในคลาสที่ผู้ใช้กำหนด
Ionuț G. Stan

1
จากphp.net/manual/en/language.operators.comparison.phpคลาสในตัวสามารถกำหนดการเปรียบเทียบของตัวเองคลาสที่แตกต่างไม่สามารถเทียบได้คลาสเดียวกัน - เปรียบเทียบคุณสมบัติเช่นเดียวกับอาร์เรย์ (PHP 4), PHP 5 มี คำอธิบายของตัวเอง
ซาอูล

7
ระวังเมื่อเปรียบเทียบวันที่และเวลาที่ไม่มีชุดชั่วโมงและหนึ่งชุดที่มีมัน (ตัวสร้างเริ่มต้น)
max4ever

1
โปรดทราบฉันเชื่อว่าคำเตือนคือหากคุณเพียงสนใจในการเปรียบเทียบวันที่คุณอาจมองข้ามความจริงที่ว่าชั่วโมงนั้นแตกต่างกันดังนั้นทั้งสองDateTimeที่มีวันเดียวกันจะไม่ถูกเปรียบเทียบเท่ากับเมื่อคุณเชื่อว่าควรจะ คุณสามารถแก้ไขสิ่งนี้ได้โดยตั้งองค์ประกอบเวลาของวัตถุเป็นศูนย์อย่างชัดเจนก่อนที่จะทำการเปรียบเทียบ
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

สำหรับรุ่นก่อน 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)


16
ระวังที่formatสร้างสตริงดังนั้นนั่นคือการเปรียบเทียบสตริง มันแทบจะไม่เป็นปัญหาหลังจากเวลา 1000000000 ยุค (ประมาณ 9 ก.ย. 2001) แต่ถ้าคุณต้องจัดการกับวันที่ก่อนหน้านั้นคุณอาจต้องเผชิญกับปัญหาเนื่องจากความยาวของจำนวนที่แตกต่างกัน ทั้งแปลงผลให้ตัวเลข (ลบพวกเขาทำงานมากเกินไป) cหรือใช้รูปแบบการจัดเรียงอย่างแท้จริงเช่น
MaxArt

1
@ MaxArt คุณช่วยอธิบายรายละเอียดเกี่ยวกับปัญหาเนื่องจากความยาวสตริงที่แตกต่างกันได้อย่างไร คู่มือเกี่ยวกับสตริงในบริบทตัวเลข: "หากสตริงไม่มีอักขระใด ๆ '.', 'e' หรือ 'E' และค่าตัวเลขพอดีกับข้อ จำกัด ประเภทจำนวนเต็ม (ตามที่กำหนดโดย PHP_INT_MAX) สตริง จะถูกประเมินเป็นจำนวนเต็มในกรณีอื่น ๆ ทั้งหมดจะถูกประเมินเป็นทศนิยม " วันที่ในอนาคต (ประมาณ 2038) สามารถล้นล้นจำนวนเต็ม 32- บิตลงนาม แต่ปัญหาของวันที่เก่ากว่าคืออะไร?
Adrian Günter

1
@ AdrianGünterปัญหาคือว่าเราจะไม่อยู่ในบริบทที่เป็นตัวเลข แต่เราจะจัดการกับสตริง ตัวเลข แต่ยังคงสตริง ดังนั้นการเปรียบเทียบสตริงจะทำ
MaxArt


2
@ FrédéricMarchalใช่ฉันได้เรียนรู้ในภายหลังว่าความคิดเห็นก่อนหน้าของฉันเป็นจริงเท็จ PHP มีวิธีที่ชั่วร้ายจริงๆในการจัดการกับกรณีเหล่านี้ไม่มีภาษาอื่น ๆ (อย่างที่ฉันรู้) ปลดมันเป็นตัวเลขเมื่อคุณมีสองสายที่จะเปรียบเทียบ มันจะไขรหัสของคุณจริงๆถ้าคุณต้องการเปรียบเทียบการทำพจนานุกรม
MaxArt

20

หากคุณต้องการเปรียบเทียบวันที่และไม่ใช่เวลาคุณสามารถใช้สิ่งนี้:

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

5
คุณยังสามารถตั้งเวลาในการรีเซ็ต $d1->setTime(0, 0, 0);
Athlan

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

ดีที่รู้! นี่เป็นเพียงความหมายเพื่อเปรียบเทียบเวลาเท่านั้น
Kyle Coots

-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 คุณคิดว่าข้อ จำกัด การประทับเวลารบกวนรหัสข้างต้นซึ่งมีเวลาวันที่ปัจจุบันทั้งหมดโปรดอ่านรหัสอีกครั้งโดยทั่วไปตรวจสอบหาผู้ชาย $ คาดหวังวันที่ซึ่งจะอยู่ในเดือนปัจจุบันเสมอ ฉันไม่คิดอย่างนั้นเราควรคิดถึงข้อ จำกัด การประทับเวลาที่นี่ในกรณีนี้
Tarun Gupta

ฉันรู้ แต่มันไม่ใช่วิธีที่แนะนำ (ฉันไม่ได้ลงคะแนน :-))
Steel Brain

คุณช่วยแนะนำวิธีแนะนำได้ไหม
Tarun Gupta

แน่นอน$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.