What can use for DateTime::diff() for PHP 5.2?
Asked Answered
S

10

26

Is there any function equivalent to DateTime::diff() in PHP 5.2?

My local server is PHP 5.3 and using DateTime::diff(). then I found that my live site uses PHP 5.2 and gives an error.

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

The PHP code:

 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;
Soloman answered 27/10, 2010 at 12:36 Comment(0)
R
41

Spudley's answer doesn't work for me--subtracting any DateTime from another gives 0 on my system.

I was able to get it to work by using DateTime::format with the 'U' specifier (seconds since Unix epoch):

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

This works on both my dev system (5.3.4) and my deployment system (5.2.11).

Rick answered 5/4, 2011 at 6:39 Comment(4)
Almost perfect, except you used abs(), which assume it is always positive.Sommer
Thanks for pointing that out, @ShivanRaptor. I looked back at the code I wrote this for, and it requires a positive value, and always compares today with a date in the past. The bug in that code was that I subtracted today from the start date, instead of the other way around, so I used abs() to convert it to a positive value. I've updated the sample above to return a negative value if the end date is before the start date, which is the default behavior of DateTime::diff().Rick
I needed to add perenthesis to the upper part of division: $days = round(($end->format('U') - $start->format('U')) / (60*60*24))Cumin
This not working properly, using DateTime::diff() I got 340 days and with this code 341. Don't recommend to use it on production.Garnierite
V
6

I just needed that ( unfortunately ) for a WordPress plugin. This I use the function in 2 times:

  1. In my class calling ->diff() ( my class extends DateTime, so $this is the reference DateTime )

    function diff ($secondDate){
        $firstDateTimeStamp = $this->format("U");
        $secondDateTimeStamp = $secondDate->format("U");
        $rv = ($secondDateTimeStamp - $firstDateTimeStamp);
        $di = new DateInterval($rv);
        return $di;
    }
    
  2. Then I recreated a fake DateInterval class ( because DateInterval is only valid in PHP >= 5.3 ) as follows:

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

Hope that helps somebody.

Vincenz answered 9/7, 2012 at 6:17 Comment(1)
nice, but why not use the mod function (%) (and integer division) instead of looping to get remainderFiretrap
V
3

I use this, seems to work alright - obviously you can add a second parameter to make it more flexible:

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 ...
}
Vase answered 2/3, 2012 at 12:31 Comment(0)
D
3

I was trying to improve Christopher Pickslay's answer.

I made this function that returns and object with most of the properties from the original DateInterval object.

There is no "days" property, because it seems to be some bug in my test server (it always return 6015) .

Also, I am assuming every month has 30 days, which is definitely not precise, but may help.

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;
}    
Dolley answered 11/5, 2012 at 12:49 Comment(1)
with this instead 30 we can calculate the exact days the month has: cal_days_in_month(CAL_GREGORIAN, 8, 2003);Rillings
B
2

Yes, it's annoying that feature didn't make it into PHP5.2.

I'll assume you can't upgrade to 5.3? You should look into it; there's very little reason not to upgrade; but I'll assume you can't for whatever the reason.

First tip: If you only need a diff of less than 24hours, you can simply subtract the two time stamps, and do $time_diff = date('H:i:s',$subtracted_value);

If you're doing more than 24 hour diffs, but you're okay with just returning the number of days along with the time difference, you can expand on the above technique by doing a modulus calculation on the subtrated value, against the number of seconds in a day (ie 24*60*60, which is 86400)

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

If you need weeks, you can of course do $days_diff % 7.

Unfortunately, the manual technique breaks down after weeks, because months and years are variable in length (technically days are too, given daylight saving, but you can probably ignore that, especially as you're only ever going to be one hour out, at the most), but hopefully that's good enough to get you started.

Beadsman answered 27/10, 2010 at 12:47 Comment(3)
Shouldn't you just divide by 86400, not modulus?Lazybones
@Rocket.... hmm, possibly. This answer was a while ago, so I can't remember what I was thinking, but you may well be right.Beadsman
I realize this was an old answer, but I found it on Google after searching for how to use DateTime::diff() on PHP 5.2.Lazybones
W
2

Read the contrib notes in the PHP date_diff page https://www.php.net/manual/en/function.date-diff.php

Wastepaper answered 17/2, 2011 at 21:25 Comment(0)
E
2

Spudley was close, but you need to use gmdate not date.

So this works for 24 hours or less (if it's a positive value at least):

$difference = $date2->format('U') - $date1->format('U');
$time_diff = gmdate('H:i:s',$difference);
Enidenigma answered 4/7, 2011 at 0:2 Comment(0)
H
0

PHP has methods for working with Unix timestamps.

As has been noted by others, by working with seconds since the Unix date, it is easy to calculate times.

PHP's strtotime() converts a date to a timestamp:

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

If you wish to calculate till the current time, time() provides the timestamp of "now":

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

86400 is the number of seconds in a day.
If you wish to convert to years use 31557000, which is almost exactly 365.24219 * 86400.

An added advantage here is that strtotime can take the input date in almost any human readable format, so it is very easy to work with within the code.

Hoist answered 21/7, 2011 at 11:3 Comment(0)
C
0

Please observe that if your DateTime object was created from a date string without any timezone information (as in '2012-01-01 05:00:00' like from mysql), then setting the timezone later with DateTimeZone objects via setTimeZone() does not change the DateTime objects internal timestamp.

$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
Commission answered 26/9, 2012 at 10:38 Comment(0)
R
0

Here is the best solution for your question.

<?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;
}
?>
Reames answered 24/2, 2016 at 6:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.