2010-10-27 30 views
25

Có chức năng nào tương đương với DateTime :: diff() trong PHP 5.2 không?Điều gì có thể sử dụng cho DateTime :: diff() cho PHP 5.2?

Máy chủ cục bộ của tôi là PHP 5.3 và sử dụng DateTime :: diff(). sau đó tôi thấy rằng trang web trực tiếp của tôi sử dụng PHP 5.2 và đưa ra một lỗi.

Fatal error: Call to undefined method DateTime::diff() in /var/www/some/other/dir/web/daikon/modules/projects/views/admin/log/admin_log_list.php on line 40 

Mã PHP:

foreach ($logs as $key => $list){ 
... 
// show date in European way dd-mm-yyyy not in MySQL way yyyy-mm-dd 
    $newdate =new DateTime($list['date']) ; 
    echo "<td class=\"left\" width=\"8%\">".$newdate->format('d-m-Y')."</td>\n"; 
    $starttime = new DateTime($list['start_time']); 
    echo "<td width=\"7%\">".date_format($starttime, 'H:i')."</td>\n"; 
    $finishtime = new DateTime($list['finish_time']); 
    echo "<td width=\"8%\">".date_format($finishtime, 'H:i')."</td>\n"; 
    $timediff = 0; 
    $interval = $starttime->diff($finishtime); 
    $hours = $interval->format('%h'); 
    $minutes = $interval->format('%i'); 
    $timediff = $hours * 60 + $minutes; 
+0

tại sao bạn không chọn câu trả lời? – realtebo

Trả lời

2

Có, đó là gây phiền nhiễu rằng tính năng không làm cho nó thành PHP5.2.

Tôi giả sử bạn không thể nâng cấp lên 5.3? Bạn nên nhìn vào nó; có rất ít lý do để không nâng cấp; nhưng tôi sẽ cho rằng bạn không thể vì bất cứ lý do gì.

mũi thứ nhất: Nếu bạn chỉ cần một diff dưới 24 giờ, bạn chỉ có thể trừ đi tem thời gian hai, và làm $time_diff = date('H:i:s',$subtracted_value);

Nếu bạn đang làm hơn 24 diffs giờ, nhưng bạn đang okay chỉ cần trả lại số ngày cùng với chênh lệch thời gian, bạn có thể mở rộng kỹ thuật trên bằng cách thực hiện phép tính mô đun trên giá trị được trừ, so với số giây trong một ngày (tức là 24 * 60 * 60, là 86400)

$subtracted_value = $date1 - $date2; 
$days_diff = $subtracted_value % 86400; 
$time_diff = date('H:i:s',$subtracted_value); 

Nếu bạn cần tuần, tất nhiên bạn có thể làm $days_diff % 7. Thật không may, kỹ thuật thủ công bị hỏng sau nhiều tuần, bởi vì tháng và năm có độ dài thay đổi (ngày kỹ thuật cũng vậy, được tiết kiệm ánh sáng ban ngày, nhưng bạn có thể bỏ qua điều đó, đặc biệt khi bạn chỉ là một giờ, nhiều nhất), nhưng hy vọng điều đó đủ tốt để bạn bắt đầu.

+0

Không nên bạn chỉ chia cho 86400, không phải mô đun? –

+0

@Rocket .... hmm, có thể.Câu trả lời này đã được một thời gian trước, vì vậy tôi không thể nhớ những gì tôi đã suy nghĩ, nhưng bạn cũng có thể đúng. – Spudley

+0

Tôi nhận ra đây là câu trả lời cũ, nhưng tôi đã tìm thấy nó trên Google sau khi tìm kiếm cách sử dụng 'DateTime :: diff()' trên PHP 5.2. –

38

câu trả lời Spudley của không làm việc cho tôi - trừ bất cứ một DateTime từ một cho 0 trên hệ thống của tôi.

tôi đã có thể để làm cho nó hoạt động bằng cách sử dụng DateTime :: format có 'U' specifier (giây kể từ Unix kỷ nguyên):

$start = new DateTime('2010-10-12'); 
$end = new DateTime(); 
$days = round(($end->format('U') - $start->format('U'))/(60*60*24)); 

này hoạt động trên cả hệ thống dev của tôi (5.3.4) và hệ thống triển khai của tôi (5.2.11).

+2

Gần như hoàn hảo, ngoại trừ bạn đã sử dụng 'abs()', cho rằng nó luôn luôn là dương. – Raptor

+1

Cảm ơn bạn đã chỉ ra điều đó, @ShivanRaptor. Tôi nhìn lại mã tôi đã viết nó, và nó đòi hỏi một giá trị tích cực, và luôn luôn so sánh ngày hôm nay với một ngày trong quá khứ. Lỗi trong mã đó là tôi đã trừ ngày hôm nay từ ngày bắt đầu, thay vì theo cách khác, vì vậy tôi đã sử dụng 'abs()' để chuyển đổi nó thành giá trị dương. Tôi đã cập nhật mẫu ở trên để trả về giá trị âm nếu ngày kết thúc trước ngày bắt đầu, đó là hành vi mặc định của 'DateTime :: diff()'. –

+0

Tôi cần thêm dấu ngoặc vào phần trên của phép chia: '$ days = round (($ end-> format ('U') - $ start-> format ('U'))/(60 * 60 * 24)) ' –

2

Spudley đã đóng, nhưng bạn cần sử dụng gmdate không có ngày.

Vì vậy, các công trình này trong 24 giờ hoặc ít hơn (nếu đó là một giá trị tích cực ít nhất):

$difference = $date2->format('U') - $date1->format('U'); 
$time_diff = gmdate('H:i:s',$difference); 
0

PHP có phương pháp để làm việc với timestamps Unix.

Như đã được ghi nhận bởi những người khác, bằng cách làm việc với vài giây kể từ ngày Unix, nó rất dễ dàng để tính toán lần.

strtotime PHP() chuyển đổi một ngày để một dấu thời gian:

$diff = round((strtotime($list['start']) - strtotime($list['finish']))/86400); 

Nếu bạn muốn tính đến thời điểm hiện tại, thời gian() cung cấp dấu thời gian của "bây giờ":

$diff = round((time() - strtotime($list['date']))/86400); 

86400 là số giây trong một ngày.
Nếu bạn muốn chuyển đổi sang sử dụng năm 31.557.000, đó là gần như chính xác 365,24219 * 86400.

Một bổ sung lợi thế ở đây là strtotime có thể mất từ ​​ngày đầu vào trong hầu hết các định dạng có thể đọc được con người, vì vậy nó là rất dễ dàng để làm việc với bên trong mã.

3

tôi sử dụng này, dường như làm việc ổn - rõ ràng là bạn có thể thêm một tham số thứ hai để làm cho nó linh hoạt hơn:

function GetDateDiffFromNow($originalDate) 
{ 
    $unixOriginalDate = strtotime($originalDate); 
    $unixNowDate = strtotime('now'); 
    $difference = $unixNowDate - $unixOriginalDate ; 
    $days = (int)($difference/86400); 
    $hours = (int)($difference/3600); 
    $minutes = (int)($difference/60); 
    $seconds = $difference; 

    // now do what you want with this now and return ... 
} 
3

Tôi đã cố gắng để cải thiện câu trả lời Christopher Pickslay của.

Tôi đã thực hiện chức năng này trả về và đối tượng với hầu hết các thuộc tính từ đối tượng DateInterval gốc.

Không có thuộc tính "ngày", vì có vẻ như là some bug trong máy chủ thử nghiệm của tôi (nó luôn trả về 6015).

Ngoài ra, tôi giả sử mỗi tháng có 30 ngày, điều này chắc chắn không chính xác nhưng có thể hữu ích.

function dateTimeDiff($date1, $date2) { 

    $alt_diff = new stdClass(); 
    $alt_diff->y = floor(abs($date1->format('U') - $date2->format('U'))/(60*60*24*365)); 
    $alt_diff->m = floor((floor(abs($date1->format('U') - $date2->format('U'))/(60*60*24)) - ($alt_diff->y * 365))/30); 
    $alt_diff->d = floor(floor(abs($date1->format('U') - $date2->format('U'))/(60*60*24)) - ($alt_diff->y * 365) - ($alt_diff->m * 30)); 
    $alt_diff->h = floor(floor(abs($date1->format('U') - $date2->format('U'))/(60*60)) - ($alt_diff->y * 365*24) - ($alt_diff->m * 30 * 24) - ($alt_diff->d * 24)); 
    $alt_diff->i = floor(floor(abs($date1->format('U') - $date2->format('U'))/(60)) - ($alt_diff->y * 365*24*60) - ($alt_diff->m * 30 * 24 *60) - ($alt_diff->d * 24 * 60) - ($alt_diff->h * 60)); 
    $alt_diff->s = floor(floor(abs($date1->format('U') - $date2->format('U'))) - ($alt_diff->y * 365*24*60*60) - ($alt_diff->m * 30 * 24 *60*60) - ($alt_diff->d * 24 * 60*60) - ($alt_diff->h * 60*60) - ($alt_diff->i * 60)); 
    $alt_diff->invert = (($date1->format('U') - $date2->format('U')) > 0)? 0 : 1 ; 

    return $alt_diff; 
}  
+0

tốt, cố định lỗ - nhưng sự lặp lại trông hơi dư thừa đối với tôi ... – BananaAcid

+0

với điều này thay vì 30 chúng ta có thể tính toán chính xác ngày tháng có: cal_days_in_month (CAL_GREGORIAN, 8, 2003); –

6

Tôi chỉ cần điều đó (không may) đối với plugin WordPress. Này, tôi sử dụng các chức năng trong 2 lần:

  1. Trong lớp tôi gọi -> diff() (lớp học của tôi kéo dài DateTime, vì vậy $ này là tài liệu tham khảo DateTime)

    function diff ($secondDate){ 
        $firstDateTimeStamp = $this->format("U"); 
        $secondDateTimeStamp = $secondDate->format("U"); 
        $rv = ($secondDateTimeStamp - $firstDateTimeStamp); 
        $di = new DateInterval($rv); 
        return $di; 
    } 
    
  2. Sau đó, tôi tạo lại lớp DateInterval giả (vì DateInterval chỉ hợp lệ trong PHP> = 5.3) như sau:

    Class DateInterval { 
        /* Properties */ 
        public $y = 0; 
        public $m = 0; 
        public $d = 0; 
        public $h = 0; 
        public $i = 0; 
        public $s = 0; 
    
        /* Methods */ 
        public function __construct ($time_to_convert /** in seconds */) { 
         $FULL_YEAR = 60*60*24*365.25; 
         $FULL_MONTH = 60*60*24*(365.25/12); 
         $FULL_DAY = 60*60*24; 
         $FULL_HOUR = 60*60; 
         $FULL_MINUTE = 60; 
         $FULL_SECOND = 1; 
    
    //  $time_to_convert = 176559; 
         $seconds = 0; 
         $minutes = 0; 
         $hours = 0; 
         $days = 0; 
         $months = 0; 
         $years = 0; 
    
         while($time_to_convert >= $FULL_YEAR) { 
          $years ++; 
          $time_to_convert = $time_to_convert - $FULL_YEAR; 
         } 
    
         while($time_to_convert >= $FULL_MONTH) { 
          $months ++; 
          $time_to_convert = $time_to_convert - $FULL_MONTH; 
         } 
    
         while($time_to_convert >= $FULL_DAY) { 
          $days ++; 
          $time_to_convert = $time_to_convert - $FULL_DAY; 
         } 
    
         while($time_to_convert >= $FULL_HOUR) { 
          $hours++; 
          $time_to_convert = $time_to_convert - $FULL_HOUR; 
         } 
    
         while($time_to_convert >= $FULL_MINUTE) { 
          $minutes++; 
          $time_to_convert = $time_to_convert - $FULL_MINUTE; 
         } 
    
         $seconds = $time_to_convert; // remaining seconds 
         $this->y = $years; 
         $this->m = $months; 
         $this->d = $days; 
         $this->h = $hours; 
         $this->i = $minutes; 
         $this->s = $seconds; 
        } 
    } 
    

Mong rằng sẽ giúp ai đó.

+0

đẹp, nhưng tại sao không sử dụng hàm mod ('%') (và phân chia số nguyên) thay vì lặp để nhận phần còn lại –

0

Hãy quan sát rằng nếu đối tượng DateTime của bạn được tạo từ chuỗi ngày không có bất kỳ thông tin múi giờ nào (như trong '2012-01-01 05:00:00' như từ mysql), sau đó đặt múi giờ sau đó với đối tượng DateTimeZone qua setTimeZone() không thay đổi dấu thời gian nội bộ của đối tượng DateTime.

$localtime = new DateTime('2012-01-01 08:00:00+02:00'); // Europe/Copenhagen (+ daylight savings) 
$localtime->setTimezone(new DateTimeZone('UTC')); // convert local time to utc 

$utctime = new DateTime('2012-01-01 06:00:00'); // timezone assumed utc, but is in fact unknown 
$utctime->setTimezone(new DateTimeZone('UTC')); // trying to rectify missing timezone which fails, because the internal timestamp isn't modified, although any other format than 'U' may indicate so 
#$utctime = new DateTime('2012-01-01 06:00:00+00:00'); // timezone stated, this works 

$diff = intval($localtime->format('U')) - intval($utctime->format('U')); 
echo $diff; // expecting zero 
0

Đây là giải pháp tốt nhất cho câu hỏi của bạn.

<?php 

/* Find difference between two dates in days. PHP 5.2.x. */ 

$d1 = date('Y-m-d', strtotime('2013-06-13')); 
$d2 = date("Y-m-d"); 
echo diff($d1, $d2); 

function diff($date1, $date2) { 
    $diff = abs(strtotime($date2) - strtotime($date1)); 
    $years = floor($diff/(365*60*60*24)); 
    $months = floor(($diff - $years * 365*60*60*24)/(30*60*60*24)); 
    $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/(60*60*24)); 
    return $days; 
} 
?> 
Các vấn đề liên quan