2012-01-04 47 views
6

tôi đã cố gắng để so sánh sự khác biệt giữa 2 ngày, nhưng có vẻ như kết quả là khá sai lầm, ví dụ mã này:PHP: Datetime :: Diff kết quả so sánh

$datetime1 = new DateTime('2009-10-11'); 
$datetime2 = new DateTime('2009-10-13'); 
$interval = $datetime1->diff($datetime2); 
echo $interval->format('%R%a days')."<br />"; 

$datetime1 = new DateTime('2009-10-11'); 
$datetime2 = new DateTime('2009-10-15'); 
$interval2 = $datetime1->diff($datetime2); 
echo $interval2->format('%R%a days')."<br />"; 

if($interval == $interval2){ echo "true"; }else{echo "false"; } 

Returns đúng, nhưng ở trên, bạn có thể thấy sự khác biệt ngày không giống nhau, trên thực tế, các bản in echo +2 và +4. Bất kỳ ý tưởng nào về cách so sánh 2 khác biệt về ngày?

EDIT: datetime :: diff trả về một đối tượng dateinterval, trên thực tế nó không thực hiện toán tử so sánh, https://bugs.php.net/bug.php?id=49914 tôi sẽ sử dụng dateinterval vars để kiểm tra sự khác biệt, cảm ơn cho câu trả lời

+1

so sánh đối tượng =/= so sánh giá trị. – hakre

Trả lời

7

Dường như DateInterval không thực hiện chức năng so sánh bên trong. Các tiện ích mở rộng được phép xác định các quy tắc so sánh tùy chỉnh cho các lớp được xác định trước của chúng. Rõ ràng nó rơi trở lại một so sánh lỏng lẻo rằng các đối tượng là của cùng một lớp.

This feature request cung cấp bản vá để thêm chức năng này vào, nhưng dường như không có chức năng này vào nguồn bất kỳ lúc nào.

Để khắc phục vấn đề này, bạn có thể so sánh từng biến thành viên của đối tượng của bạn mình (năm, tháng vv) hoặc bạn có thể cast từng đối tượng đến một mảng:

if ((array) $interval == (array) $interval2) { 
    echo 'true'; 
} else { 
    echo 'false'; 
} 
0

Bạn đang chuyển nhượng $ datetime1-> diff ($ datetime2) cả hai đến $ interval và $ interval2, do đó, chúng có cùng giá trị giống nhau

+0

Bạn có thể thấy rằng trên dòng 7 tôi đã thay đổi ngày;) – alex88

3

Bạn chỉ có comparing that the two objects­Docs cùng loại (và cùng giá trị của đạo cụ), nhưng không phải là giống hệt:

if ($interval === $interval2) {echo "true";} else {echo "false";} 
       ^^^ 

Lưu ý rằng bạn đang so sánh đối tượng chứ không phải so sánh giá trị, như với chuỗi.

+0

Ồ, bạn nói đúng, cảm ơn bạn! – alex88

+0

Mỗi [đối tượng so sánh] (http://php.net/manual/en/language.oop5.object-comparison.php), các đối tượng cùng loại với các biến thành viên công khai giống nhau nên được xem là bình đẳng; không chắc chắn điều này đáng tin cậy như thế nào áp dụng cho các lớp được xác định trước mặc dù. – cmbuckley

+0

@cbuckley: * "Lưu ý: Tiện ích mở rộng có thể xác định quy tắc riêng để so sánh đối tượng của chúng." * - vì vậy mọi thứ có thể xảy ra;) – hakre

0

Tôi nhớ có một chức năng để so sánh các ngày trong php như thế này.

compare_dates($start_date,$end_date); 
+3

Không, không có –

+0

Không thể tìm thấy:/ – alex88

+0

Mã của bạn được lấy từ http://php.net/manual/en/datetime.diff.php Trong cùng một trang, bạn sẽ tìm thấy cú pháp so sánh ở đây http://php.net/manual/en/ref.datetime.php – Anil

0

tôi đã thực hiện so sánh giữa hai DateIntervals sử dụng cách sau:

version_compare(join('.', (array) $dateIntervalA), join('.', (array) $dateIntervalB)); 
+2

Tôi sẽ không lạm dụng chức năng so sánh các thẻ phiên bản để so sánh các khoảng ngày tháng. – Sven

2

Tôi đã mở rộng lớp php. So sánh phương pháp so sánh giá trị. Nó sử dụng thứ tự "tự nhiên" của các biến trong lớp DateInterval php. Chu kỳ foreach đi đầu tiên qua nhiều năm, sau đó hàng tháng, sau đó ngày, vv Nó có lẽ không phải là một giải pháp rất di động, nhưng nó có vẻ là làm việc tốt trong php 5.3.

/** 
* Description of DateInterval 
* 
* @author Santhos 
*/ 
class DateInterval extends \DateInterval 
{  
    /** 
    * compares two date intervals 
    * returns: 
    * 0 - when they are equal 
    * less than zero - $a is less than $b 
    * greater than zero - $a is greater than $b 
    * 
    * @param \Designeo\Utils\DateInterval $dateInterval 
    * @return int 
    */ 
    public static function compare($a, $b) 
    { 
     // check parameters 
     self::isDateInterval($a); 
     self::isDateInterval($b); 

     foreach ($a as $key => $value) {    
      // after seconds 's' comes 'invert' and other crap we do not care about 
      // and it means that the date intervals are the same 
      if ($key == 'invert') {     
       return 0; 
      } 

      // when the values are the same we can move on 
      if ($a->$key == $b->$key) { 
       continue; 
      } 

      // finally a level where we see a difference, return accordingly 
      if ($a->$key < $b->$key) { 
       return -1; 
      } else { 
       return 1; 
      } 
     } 
    } 

    private static function isDateInterval($object) 
    { 
     if (!is_a($object, 'DateInterval')) { 
      throw new \Exception('Parameter dateInterval type has to be a Dateinterval.'); 
     } 
    } 

    public function compareToAnother($dateInterval) { 
     return self::compare($this, $dateInterval); 
    } 
} 
Các vấn đề liên quan