Jump to content

substract two dates and convert remaining time


DJMurtz

Recommended Posts

Hi,

Right now I have two dates. One date is (for example) [b]2007-04-15 00:00:00[/b] The other date is the current date. I want to substract the current date from the '2007-04-15 00:00:00' date. I did this by converting both dates to a UNIX timestamp and then substracting them from eachother.

Next thing I did was this:

[code]
<?php
        $iTimeLeft = strtotime($aMembersInfo['expiredate']) - time();
        $iYears = 0;
        $iDays = 0;
        $iHours = 0;
        $iMinutes = 0;
        $iSeconds = 0;
        
        while($iTimeLeft >= 31536000) {
            $iTimeLeft -= 31536000;
            $iYears += 1;
        }
        while($iTimeLeft >= 86400) {
            $iTimeLeft -= 86400;
            $iDays += 1;
        }
        while($iTimeLeft >= 3600) {
            $iTimeLeft -= 3600;
            $iHours += 1;
        }
        while($iTimeLeft >= 60) {
            $iTimeLeft -= 60;
            $iMinutes += 1;
        }
        if($iTimeLeft >= 0) {
            $iSeconds = $iTimeLeft;
        }
        if($iYears != 0) {
            $iTimeLeft = $iYears . 'y ' . $iDays . 'd';
        } elseif($iDays != 0 && $iDays != 1) {
            $iTimeLeft = $iDays . 'd';
        } elseif($iDays == 1) {
            $iTimeLeft = $iDays . 'd ' . $iHours . 'h';
        } elseif($iHours != 0) {
            $iTimeLeft = $iHours . 'h ' . $iMinutes . 'm';
        } elseif($iMinutes != 0) {
            $iTimeLeft = $iMinutes . 'm ' . $iSeconds . 's';
        } elseif($iSeconds != 0) {
            $iTimeLeft = $iSeconds . 's';
        } else {
            $iTimeLeft = 'Disabled';
        }
?>
[/code]

As you can see I started counting how many years, months, days, hours, minutes and finally seconds fit into the UNIX timestamp I got from substracting the two dates. After this I started putting the number of years, months, etc into their own variables and parse them in the way I want on the screen.

All of this works great, with one downside. It's inacurate. As you can see in my code I presume that a month has always 30 days, and a year 365 days. This isn't correct and thus the output is false.

I've been trying to think of a way to get the same output, but with correct numbers but have so far found nothing that will help me do this. Does anyone of you know a solution to my problem? I thank you in advance!
Link to comment
Share on other sites

Well, you can use strtotime() to convert "English" dates to UNIX timestamps; then subtract them

[a href=\"http://us3.php.net/manual/en/function.strtotime.php\" target=\"_blank\"]http://us3.php.net/manual/en/function.strtotime.php[/a]
Link to comment
Share on other sites

[!--quoteo(post=365736:date=Apr 18 2006, 01:08 AM:name=poirot)--][div class=\'quotetop\']QUOTE(poirot @ Apr 18 2006, 01:08 AM) [snapback]365736[/snapback][/div][div class=\'quotemain\'][!--quotec--]
Well, you can use strtotime() to convert "English" dates to UNIX timestamps; then subtract them

[a href=\"http://us3.php.net/manual/en/function.strtotime.php\" target=\"_blank\"]http://us3.php.net/manual/en/function.strtotime.php[/a]
[/quote]

Thanks for the suggestion, but you can see that I already did this in my example..

Just to make it more clear:


Here I convert everything to UNIX timestamps:
$iTimeLeft = strtotime($aMembersInfo['expiredate']) - time();

After that I start substracting 31536000 seconds (1 year):
while($iTimeLeft >= 31536000) {
$iTimeLeft -= 31536000;
$iYears += 1;
}

After that days, hours, minutes and seconds.
But as I stated above, this is inacurate, because a year isn't always 365 days and a month isnt always 30 days.

I'm on to something tho, I think I figured it out, just making some final tweaks right now
Link to comment
Share on other sites

After messing around with php I got what I needed:

[code]
<?php
        // Calculate time left till deactivation account and echo in cel.
        
        // Extract variables from expire date/time
        $aExpireDate = explode(' ', $aMembersInfo['expiredate']);
        $aExpireTime = $aExpireDate[1];
        $aExpireDate = $aExpireDate[0];
        
        $aExpireDate = explode('-', $aExpireDate);
        $aExpireTime = explode(':', $aExpireTime);
        // Extract variables from current date/time
        $aCurrentDate = explode(' ', $aMembersInfo['now']);
        $aCurrentTime = $aCurrentDate[1];
        $aCurrentDate = $aCurrentDate[0];
        
        $aCurrentDate = explode('-', $aCurrentDate);
        $aCurrentTime = explode(':', $aCurrentTime);
        
        // Calculate differences between now and expire date
        $iDiffYears  = $aExpireDate[0] - $aCurrentDate[0];
        $iDiffMonths = $aExpireDate[1] - $aCurrentDate[1];
        $iDiffDays   = $aExpireDate[2] - $aCurrentDate[2];
    
        $iDiffHours  = $aExpireTime[0] - $aCurrentTime[0];
        $iDiffMins   = $aExpireTime[1] - $aCurrentTime[1];
        $iDiffSecs   = $aExpireTime[2] - $aCurrentTime[2];
    
        // Make sure correct number of days, months and years are shown
        if($iDiffDays < 0) {
            $iDiffMonths--;
            $iDiffDays += date("t",mktime(0,0,0,date("m")-1));
        }
        if($iDiffMonths < 0) {
            $iDiffYears--;
            $iDiffMonths += 12;
        }
        // We don't use months, convert them to days
        while($iDiffMonths != 0) {
            $iDiffMonths--;
            $iDiffDays += date("t",mktime(0,0,0,date("m")));
        }
        // Calculate time differences
        if($iDiffSecs < 0) {
            $iDiffMins--;
            $iDiffSecs += 60;
        }
        if($iDiffMins < 0) {
            $iDiffHours--;
            $iDiffMins += 60;
        }

        
        
        if($iDiffYears != 0) {
            $iTimeLeft = $iDiffYears . 'y ' . $iDiffDays . 'd';
        } elseif($iDiffDays != 0 && $iDiffDays != 1) {
            $iTimeLeft = $iDiffDays . 'd';
        } elseif($iDiffDays == 1) {
            $iTimeLeft = $iDiffDays . 'd ' . $iDiffHours . 'h';
        } elseif($iDiffHours != 0) {
            $iTimeLeft = $iDiffHours . 'h ' . $iDiffMins . 'm';
        } elseif($iDiffMins != 0) {
            $iTimeLeft = $iDiffMins . 'm ' . $iDiffSecs . 's';
        } elseif($iDiffSecs != 0) {
            $iTimeLeft = $iDiffSecs . 's';
        }
        if ($iTimeLeft{0} == '-') {
            $iTimeLeft = 'Disabled';
        }
?>
[/code]

Only problem with this method is, it's kind of a processorhog. It took php to parse 10 rows dates with the difference between them via this method [b]0.8 seconds[/b]. Maybe I can find a better way to do what I did in the above script in the future. But for now it works :)
Link to comment
Share on other sites

I just looked at your first post more carefully, and I really can't think of a good solution.

So, can I give you an advice instead? Calculating time left befire expiration is not like "oh my, it must be totally accurate"; if I were a user with more than 1 year of time I wouldn't worry about "hey, its lacking 1 day" or something as long as I know the expiration date itself.

So, you should measure the advantages and drawbacks, I would prefer something less accurate over a slow script.
Link to comment
Share on other sites

Based on a standard subtraction

[code]     Y   M   D   H   m   s
--------------------------
   2007  4  15   0   0   0
   2006  4  18   0  37  45  -
---------------------------
      0 11  26  23  22  15[/code]

this processed an array of 10 dates in 0.0016 secs on my server.

[code]
<?php
function getmicrotime(){
    list($usec, $sec) = explode(" ",microtime());
    return ((float)$usec + (float)$sec);
    }

$t1 = getmicrotime();

function datediff($exp) {

        if (strtotime($exp) < time()) {
            $t1 = getdate(strtotime($exp));
            $t2 = getdate();

        } else {
            $t2 = getdate(strtotime($exp));
            $t1 = getdate();
        }

        //seconds
        if ($t2['seconds'] > $t1['seconds']) {
            $d['seconds'] = $t2['seconds'] - $t1['seconds'];
        }
        else {
            $d['seconds'] = $t2['seconds'] + 60 -  $t1['seconds'];
            $t1['minutes'] += 1;
        }

        //minutes
        if ($t2['minutes'] > $t1['minutes']) {
            $d['minutes'] = $t2['minutes'] - $t1['minutes'];
        }
        else {
            $d['minutes'] = $t2['minutes'] + 60 -  $t1['minutes'];
            $t1['hours'] += 1;
        }

        //hours
        if ($t2['hours'] > $t1['hours']) {
            $d['hours'] = $t2['hours'] - $t1['hours'];
        }
        else {
            $d['hours'] = $t2['hours'] + 24 -  $t1['hours'];
            $t1['mday'] += 1;
        }

        //days
        if ($t2['mday'] > $t1['mday']) {
            $d['mday'] = $t2['mday'] - $t1['mday'];
        }
        else {
               // get days in current month
            $dim = date('t', mktime(0,0,0,$t1['mon'],1,$t1['year']));

            $d['mday'] = $t2['mday'] + $dim -  $t1['mday'];
            $t1['mon'] += 1;
        }

        //months
        if ($t2['mon'] > $t1['mon']) {
            $d['mon'] = $t2['mon'] - $t1['mon'];
        }
        else {
            $d['mon'] = $t2['mon'] + 12 -  $t1['mon'];
            $t1['year'] += 1;
        }

        //years
        $d['year'] = $t2['year'] - $t1['year'];

        return array_reverse($d);
}

$input = array (
          '2004-04-15 00:00:00',
          '2008-05-31 00:00:00',
          '2007-12-15 00:00:00',
          '2006-05-31 00:00:00',
          '2007-04-15 00:00:00',
          '2006-06-01 00:00:00',
          '2010-04-15 00:00:00',
          '2006-09-31 00:00:00',
          '2007-02-01 00:00:00',
          '2008-08-08 00:00:00'
);

foreach($input as $dt) {
    $d = datediff($dt);

    foreach ($d as $k=>$v) echo "<b>$v</b> $k  ";
    echo '<br>';
}

$t2 = getmicrotime();
echo $t2-$t1;
?>[/code]
Link to comment
Share on other sites

[!--quoteo(post=366019:date=Apr 18 2006, 04:40 PM:name=Jean M)--][div class=\'quotetop\']QUOTE(Jean M @ Apr 18 2006, 04:40 PM) [snapback]366019[/snapback][/div][div class=\'quotemain\'][!--quotec--]
Thanks alot :)

That works great, stupid of me not to think of the 'simple math' stuff ;)
[/quote]

Looking deeper into it it seems your technique is basicly the same as mine.
After implementing it it gave me the same slow parse time.

After commenting out other lines in the while loop I found the problem (but didn't solve it yet):
[code]
$aPlanInfo = mysql_fetch_assoc(mysql_query("SELECT term, type FROM plans WHERE id = " . $aMembersInfo['plan']));
[/code]

I have no clue why a simple query could slow the script down by almost 1 second. I [b]am[/b] testing this localy but I never had this kind of problem before? Could it be that me running the script localy might be causing the delay? Or should I look elsewhere for the problem?
Link to comment
Share on other sites

[!--quoteo(post=366121:date=Apr 18 2006, 08:58 PM:name=Barand)--][div class=\'quotetop\']QUOTE(Barand @ Apr 18 2006, 08:58 PM) [snapback]366121[/snapback][/div][div class=\'quotemain\'][!--quotec--]
DON'T nest Mysql functions like that.

Every time you fetch a row you repeat the query!
[/quote]

I understand that, but I dont see how else to get the right data for each user, right now I have this:
[code]
    $qMembersInfo = mysql_query("SELECT NOW() AS now, plans.unixtime, plans.id, membership.*
                                FROM membership, plans " . $sWhere . $sWherePlans . "
                                ORDER BY " . $sSortDatabase . " " . $_GET['sort'] . "
                                LIMIT " . $sStart . "," . $sEnd;


    // Parse selected members in the table.
    while($aMembersInfo = mysql_fetch_assoc($qMembersInfo)) {
        // Get plan info for member
        $aPlanInfo = mysql_fetch_assoc(mysql_query("SELECT term, type FROM plans WHERE id = " . $aMembersInfo['plan']));
    }
[/code]

I don't see another way to get the information I need from the selected user in the while loop...
Link to comment
Share on other sites

  • 4 weeks later...
I notice the solutions where a bit too complicated for this problem

time() function in php will return the number of seconds, so if you have two times and subtract them, you'll get the difference in seconds. All you have to do is convert that into minutes, hours, days, etc...

I wrote a small function that will do that

[code]function convert_time($seconds){
    $f_minutes = $seconds / 60;
    $i_minutes = floor($f_minutes);
    $r_seconds = intval(($f_minutes - $i_minutes) * 60);
    
    $f_hours = $i_minutes / 60;
    $i_hours = floor($f_hours);
    $r_minutes = intval(($f_hours  - $i_hours) * 60);
    
    $f_days = $i_hours / 24;
    $i_days = floor($f_days);
    $r_hours = intval(($f_days - $i_days) * 24);
    
    if ($i_days > 0) $r = "$i_days days ";
    if ($r_hours > 0) $r .= "$r_hours hours ";
    if ($r_minutes > 0) $r .= "$r_minutes min";
    else $r = "less than a minute";
    
    return $r;
}[/code]

the f_ is for float i_ is for int and r_ is the return value. I only need days, so you can keep going for months and years the same way.

Good luck,

Wesam Saif
[a href=\"http://www.nogray.com\" target=\"_blank\"]http://www.nogray.com[/a]
Link to comment
Share on other sites

  • 2 months later...
Hi,

I was playing with the convert_seconds function and found that a value of 46800 to 46859 (13 hours to 13 hours 59 seconds) returns "less than a minute".

values above 46859 and values below 46800 return the correct time.

This is the only range that I have found and I havent found out why its doing this yet.

Does anyone else have this issue?
Does anyone see where the problem is?

I am using PHP ver. 4.4.2


Thanks

Ray...
Link to comment
Share on other sites

I just checked this using the following and there are quite a few values that return less than a minute.

[code=php:0]
function convert_seconds($seconds){
    $f_minutes = $seconds / 60;
    $i_minutes = floor($f_minutes);
    $r_seconds = intval(($f_minutes - $i_minutes) * 60);
   
    $f_hours = $i_minutes / 60;
    $i_hours = floor($f_hours);
    $r_minutes = intval(($f_hours  - $i_hours) * 60);
   
    $f_days = $i_hours / 24;
    $i_days = floor($f_days);
    $r_hours = intval(($f_days - $i_days) * 24);
   
    if ($i_days > 0) $r = $i_days."d ";
    if ($r_hours > 0) $r .= $r_hours."h ";
    if ($r_minutes > 0) $r .= $r_minutes."m";
    else $r = "< a min";
   
    return $r;
}
$count = 30;
while($count < 1000000){
if(convert_seconds($count) == "< a min"){
echo  $count;
echo "<br />";
}
$count = $count + 60;
}
[/code]

Ray...
Link to comment
Share on other sites

I found it.

The else is only an else for the last if statement I just changed it to if $r is empty.

[code=php:0]
function convert_seconds($seconds){
    $f_minutes = $seconds / 60;
    $i_minutes = floor($f_minutes);
    $r_seconds = intval(($f_minutes - $i_minutes) * 60);
   
    $f_hours = $i_minutes / 60;
    $i_hours = floor($f_hours);
    $r_minutes = intval(($f_hours  - $i_hours) * 60);
   
    $f_days = $i_hours / 24;
    $i_days = floor($f_days);
    $r_hours = intval(($f_days - $i_days) * 24);
   
    if ($i_days > 0) $r = "$i_days days ";
    if ($r_hours > 0) $r .= "$r_hours hours ";
    if ($r_minutes > 0) $r .= "$r_minutes min";
    if ($r == '') $r = "less than a minute";
   
    return $r;
}
[/code]


Ray...
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.