Làm cách nào để so sánh hai đối tượng DateTime trong PHP 5.2.8?


294

Nhìn vào tài liệu PHP, hai phương thức sau đây của DateTimeđối tượng dường như sẽ giải quyết vấn đề của tôi:

Cả hai phương pháp được đánh dấu trong doco như là có sẵn trong phiên bản> = 5.3 (và không có gì ngạc nhiên nếu tôi cố gắng gọi cho họ tôi thấy họ không tồn tại). Tôi không thể tìm thấy bất kỳ tài liệu cụ thể nào cho 5.2.8 vì vậy tôi không chắc có phương thức tương đương trong phiên bản của mình không. Tôi đã google vấn đề và tìm thấy một loạt các giải pháp chiết trung, không ai trong số đó trả lời những yêu cầu rất đơn giản của tôi:

  • Làm cách nào để so sánh hai đối tượng DateTime?
  • Tôi có thể tìm tài liệu cho các phiên bản PHP trước ở đâu? Cụ thể phiên bản 5.2.8?

Đối với một số bối cảnh, tôi có mã sau đây:

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

Rõ ràng không có nhà điều hành so sánh về anh chàng này.

Biên tập

Rõ ràng giả định của tôi là hoàn toàn sai (cảm ơn Milen vì đã minh họa điều này rất hiệu quả). Có một toán tử so sánh và nó hoạt động tốt cảm ơn. Đôi khi tôi thực sự nhớ một trình biên dịch. Lỗi nằm ở đoạn mã trên, tôi chắc chắn bạn sẽ tìm thấy nó nhanh hơn nhiều so với tôi đã làm :).


1
Liên quan đến việc thiếu trình biên dịch - đặt "error_Vporting" thành "E_ALL" và bạn sẽ nhận được các thông báo như "Thông báo: Biến không xác định: start_dt in ...".
Milen A. Radev

5
Ngoài ra, xin vui lòng, sử dụng htmlentity trên $_POSTvars của bạn , hoặc mèo con sẽ bị giết.
Clement Herreman

2
Và lỗi ở đâu? : p, tôi cũng đang làm điều đó U_U. Cảm ơn trước!
castarco

2
@castarco Tôi khởi tạo $ st_dt, nhưng tôi so sánh với $ start_dt chưa được khởi tạo. Kiểm tra tên biến của bạn và có thể làm theo đề xuất của Milen và đặt error_Vporting thành E_ALL để nhận các cảnh báo biến không xác định. :)
RedBlueThing

Câu trả lời:


432

Sau đây dường như xác nhận rằng có các toán tử so sánh cho lớp 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
Cảm ơn Milen, có vẻ như tôi chỉ cần loại bỏ các giả định sai lầm của mình và đột nhiên lỗi phát sáng trong mã của tôi trở nên rõ ràng đối với tôi.
RedBlueThing

2
Hmm, điều này thật thú vị. Có thể tại một số điểm, chúng tôi sẽ có thể quá tải các toán tử trong các lớp do người dùng định nghĩa.
Ionuț G. Stan

1
Từ php.net/manual/en/lingu.operators.comparison.php Các lớp dựng sẵn có thể định nghĩa so sánh của riêng nó, các lớp khác nhau không thể so sánh được, cùng một lớp - so sánh các thuộc tính giống như mảng (PHP 4), PHP 5 có giải thích riêng
Saul

7
xem ra khi so sánh một datetime với không có giờ được đặt và một với nó được đặt (hàm tạo mặc định)
max4ever

1
TiMESPLiNTER, tôi tin rằng cảnh báo là nếu bạn chỉ quan tâm đến việc so sánh ngày, bạn có thể bỏ qua thực tế là giờ khác nhau, và do đó hai DateTimes với cùng một ngày sẽ không được so sánh như nhau khi bạn tin rằng họ nên. Bạn có thể khắc phục điều này bằng cách đặt rõ ràng các thành phần thời gian của đối tượng về 0 trước khi so sánh chúng.
Jason

52

Từ tài liệu chính thức :

Kể từ PHP 5.2.2, các đối tượng DateTime có thể được so sánh bằng các toán tử so sánh .

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

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

Đối với các phiên bản PHP trước 5.2.2 (thực tế cho bất kỳ phiên bản nào), bạn có thể sử dụng 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
Tôi thấy câu trả lời này tốt nhất vì nó trích dẫn hướng dẫn thay vì chỉ kiểm tra hành vi và cho rằng kết quả như mong đợi. SO không phải là một nơi để phỏng đoán. Bravo Roberto.
cprn

3
@roberto DateTime :: diff chỉ được thêm vào trong PHP 5.3
NeXuS

30

Bạn cũng có thể so sánh giây epoch:

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

Nguồn: http://laughingmeme.org/2007/02/27/looking-at-php5s-datetime-and-datetimezone/ (bài viết khá thú vị về DateTime)


16
Coi chừng đó formattạo ra một chuỗi , vì vậy đó là so sánh chuỗi. Đây chỉ là một vấn đề sau 1000000000 thời gian kỷ nguyên (khoảng ngày 9 tháng 9 năm 2001), nhưng nếu bạn phải xử lý các ngày trước đó, bạn có thể gặp phải các vấn đề do độ dài số khác nhau. Hoặc chuyển đổi kết quả thành số (trừ chúng cũng hoạt động) hoặc sử dụng định dạng thực sự có thể sắp xếp như thế nào c.
MaxArt

1
@MaxArt bạn có thể vui lòng giải thích các vấn đề do độ dài chuỗi khác nhau không? Hướng dẫn sử dụng, liên quan đến các chuỗi trong ngữ cảnh số: "Nếu chuỗi không chứa bất kỳ ký tự nào '.', 'E' hoặc 'E' và giá trị số phù hợp với giới hạn loại số nguyên (như được xác định bởi PHP_INT_MAX), chuỗi sẽ được đánh giá là một số nguyên. Trong tất cả các trường hợp khác, nó sẽ được đánh giá là số float. " Ngày trong tương lai (khoảng năm 2038) có thể vượt quá số nguyên 32 bit đã ký, nhưng vấn đề với ngày cũ là gì?
Adrian Günter

1
@ AdrianGünter Vấn đề là chúng ta sẽ không ở trong bối cảnh số, nhưng chúng ta sẽ xử lý các chuỗi . Số, nhưng vẫn còn chuỗi. Vì vậy, một so sánh chuỗi sẽ được thực hiện.
MaxArt


2
@ FrédéricMarchal Vâng, tôi thực sự đã học được rằng nhận xét trước đây của tôi thực tế là sai. PHP có một cách thực sự tồi tệ để xử lý các trường hợp này, không có ngôn ngữ nào khác (như tôi biết) chuyển thành số khi bạn có hai chuỗi để so sánh. Nó thực sự làm hỏng mã của bạn nếu bạn thực sự muốn thực hiện một so sánh từ điển.
MaxArt

20

Nếu bạn muốn so sánh ngày và không phải thời gian, bạn có thể sử dụng điều này:

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

5
Bạn cũng có thể đặt thời gian đặt lại. $d1->setTime(0, 0, 0);
Athlan

3

Kể từ PHP 7.x, bạn có thể sử dụng như sau:

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

dấu thời gian có một số hạn chế, bạn có thể muốn đọc stackoverflow.com/a/7229760/2652018
Bộ não thép

Rất vui được biết! Điều này chỉ có nghĩa là một cách đơn giản để so sánh thời gian.
Kyle Coots

-1

Điều này có thể giúp bạn.

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

dấu thời gian có một số hạn chế, bạn có thể muốn đọc stackoverflow.com/a/7229760/2652018
Bộ não thép

@SteelBrain bạn có nghĩ rằng giới hạn dấu thời gian làm phiền mã trên đó là tất cả thời gian ngày hiện tại, Vui lòng đọc lại mã, Về cơ bản, hãy kiểm tra anh chàng $ kì vọng sẽ luôn ở trong tháng hiện tại. Tôi không nghĩ vì vậy chúng ta nên nghĩ về giới hạn dấu thời gian ở đây trong trường hợp này.
Tarun Gupta

Tôi biết, nhưng đó không phải là một cách được đề xuất, (Tôi đã không downvote :-))
Bộ não thép

Bạn có thể đề nghị một cách được đề nghị.
Tarun Gupta

chắc chắn, $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";}chúc mừng
Bộ não thép
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.