Что можно использовать для DateTime::diff() для PHP 5.2?

Есть ли функция, эквивалентная DateTime::diff() в PHP 5.2?

Мой локальный сервер - PHP 5.3 и использует DateTime::diff(). затем я обнаружил, что мой живой сайт использует PHP 5.2 и выдает ошибку.

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

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;

person shin    schedule 27.10.2010    source источник
comment
почему ты не выбираешь ответ?   -  person realtebo    schedule 02.04.2014


Ответы (10)


Ответ Спадли не работает для меня - вычитание любого DateTime из другого дает 0 в моей системе.

Мне удалось заставить его работать, используя DateTime::format со спецификатором «U» (секунды с эпохи Unix):

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

Это работает как в моей системе разработки (5.3.4), так и в моей системе развертывания (5.2.11).

person Christopher Pickslay    schedule 05.04.2011
comment
Почти идеально, за исключением того, что вы использовали abs(), что предполагает, что оно всегда положительное. - person Raptor; 14.03.2013
comment
Спасибо, что указали на это, @ShivanRaptor. Я посмотрел на код, для которого написал это, и обнаружил, что он требует положительного значения и всегда сравнивает сегодняшнюю дату с датой в прошлом. Ошибка в этом коде заключалась в том, что я вычел сегодняшний день из даты начала, а не наоборот, поэтому я использовал abs(), чтобы преобразовать его в положительное значение. Я обновил пример выше, чтобы вернуть отрицательное значение, если дата окончания предшествует дате начала, что является поведением по умолчанию для DateTime::diff(). - person Christopher Pickslay; 14.03.2013
comment
Мне нужно было добавить многочлен в верхнюю часть деления: $days = round(($end->format('U') - $start->format('U')) / (60*60*24)) - person K. Weber; 09.05.2013
comment
Это не работает должным образом, используя DateTime::diff(), я получил 340 дней, а с этим кодом 341. Не рекомендую использовать его на производстве. - person Oleg Sapishchuk; 02.11.2015

Мне просто нужно это (к сожалению) для плагина WordPress. Это я использую функцию в 2 раза:

  1. В моем классе вызывается ->diff() (мой класс расширяет DateTime, поэтому $this является ссылкой < strong>ДатаВремя )

    function diff ($secondDate){
        $firstDateTimeStamp = $this->format("U");
        $secondDateTimeStamp = $secondDate->format("U");
        $rv = ($secondDateTimeStamp - $firstDateTimeStamp);
        $di = new DateInterval($rv);
        return $di;
    }
    
  2. Затем я воссоздал поддельный класс DateInterval (поскольку DateInterval действителен только в PHP >= 5.3) следующим образом:

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

Надеюсь, это поможет кому-то.

person nembleton    schedule 09.07.2012
comment
хорошо, но почему бы не использовать функцию мода (%) (и целочисленное деление) вместо цикла для получения остатка - person Nikos M.; 21.07.2015

Я использую это, кажется, работает нормально - очевидно, вы можете добавить второй параметр, чтобы сделать его более гибким:

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 ...
}
person Dave    schedule 02.03.2012

Я пытался улучшить ответ Кристофера Пикслея.

Я сделал эту функцию, которая возвращает и объект с большинством свойств исходного объекта DateInterval.

Свойства "days" нет, потому что это похоже на какую-то ошибку в моем тестовый сервер (он всегда возвращает 6015).

Кроме того, я предполагаю, что в каждом месяце 30 дней, что определенно неточно, но может помочь.

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;
}    
person Luciano Santana    schedule 11.05.2012
comment
с этим вместо 30 мы можем точно рассчитать количество дней в месяце: cal_days_in_month(CAL_GREGORIAN, 8, 2003); - person Alejandro Moreno; 27.08.2013

Да, раздражает, что функция не вошла в PHP5.2.

Я предполагаю, что вы не можете обновиться до 5.3? Вы должны изучить это; очень мало причин не обновляться; но я предполагаю, что вы не можете по какой-то причине.

Первый совет: если вам нужна разница менее чем за 24 часа, вы можете просто вычесть две метки времени и выполнить $time_diff = date('H:i:s',$subtracted_value);

Если вы выполняете более чем 24-часовые различия, но вы можете просто вернуть количество дней вместе с разницей во времени, вы можете расширить описанную выше технику, выполнив расчет модуля для вычитанного значения по сравнению с количеством секунд в день (т.е. 24*60*60, что составляет 86400)

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

Если вам нужны недели, вы, конечно, можете сделать $days_diff % 7.

К сожалению, ручная техника выходит из строя через несколько недель, потому что месяцы и годы имеют переменную длину (технически дни тоже, учитывая переход на летнее время, но вы, вероятно, можете игнорировать это, тем более, что вы когда-либо будете только один час, в больше всего), но, надеюсь, этого достаточно, чтобы вы начали.

person Spudley    schedule 27.10.2010
comment
Разве вы не должны просто делить на 86400, а не на модуль? - person Rocket Hazmat; 13.07.2011
comment
@Ракета .... хм, возможно. Этот ответ был некоторое время назад, поэтому я не могу вспомнить, о чем я думал, но вы вполне можете быть правы. - person Spudley; 13.07.2011
comment
Я понимаю, что это был старый ответ, но я нашел его в Google после поиска того, как использовать DateTime::diff() в PHP 5.2. - person Rocket Hazmat; 13.07.2011

Прочтите примечания на странице PHP date_diff http://us3.php.net/manual/en/function.date-diff.php

person ZCJ    schedule 17.02.2011

Спадли был близок, но вам нужно использовать gmdate, а не дату.

Так что это работает в течение 24 часов или меньше (по крайней мере, если это положительное значение):

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

В PHP есть методы для работы с временными метками Unix.

Как было отмечено другими, работая с секундами, начиная с даты Unix, легко вычислить время.

PHP strtotime() преобразует дату в метку времени:

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

Если вы хотите рассчитать до текущего времени, time() предоставляет отметку времени «сейчас»:

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

86400 — это количество секунд в сутках.
Если вы хотите преобразовать число в годы, используйте 31557000, что почти точно равно 365,24219 * 86400.

Дополнительным преимуществом здесь является то, что strtotime может принимать дату ввода практически в любом удобочитаемом формате, поэтому с ним очень легко работать в коде.

person SamGoody    schedule 21.07.2011

Обратите внимание, что если ваш объект DateTime был создан из строки даты без какой-либо информации о часовом поясе (например, «2012-01-01 05:00:00», например, из mysql), то установка часового пояса позже с объектами DateTimeZone через setTimeZone() делает не изменять внутреннюю временную метку объектов 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
person andkrup    schedule 26.09.2012

Вот лучшее решение вашего вопроса.

<?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;
}
?>
person Mohan    schedule 24.02.2016