Jump to content

Recommended Posts

Hi

 

I have a date and I am looking to work out the number of days, hours and minutes between that date/time and the current date/time. If the current date is greater than the date then it must show the difference as a negative.

 

Here are two examples:  (from time of posting)

 

Date 1: 20/07/2011 09:00:00

Date 2: 05/08/2011 20:00:00

 

The result of date 1 should be -9 days, 10 hours and 23 minutes

The result of date 2 should be 7 days, 1 hour and 38 minutes

 

The function I currently have and works for the number of days is the following:

 

function getOverdueTime($sDate )
  {

       $currentDate = time();
    
        $sDate = strtotime(sDate );
    
        $days = ($sDate - $currentDate) / 86400;
        $days = floor($days)+1;
       
        return $days.' day(s)';
     
  }

 

Can someone please explain how I would get the number of hours and minutes as well as the days?

could try

function getOverdueTime($sDate )
  {

       $currentDate = time();
    
        $sDate = strtotime(sDate );
    
        $days = ($sDate - $currentDate) / 86400;
        $days = floor($days)+1;
       
        $days = format_date($days, 'd H:i')

        return $days.' day(s)';
     
  }

could try

function getOverdueTime($sDate )
  {

       $currentDate = time();
    
        $sDate = strtotime(sDate );
    
        $days = ($sDate - $currentDate) / 86400;
        $days = floor($days)+1;
       
        $days = format_date($days, 'd H:i')

        return $days.' day(s)';
     
  }

 

Thanks for the response but what's the format_date method?

<?php
function daysBetween($fromDate)
{
$currentDate = time();
return ($currentDate - $fromDate) / 86400;
?>

 

I think that should work. You could try it out.

 

Hmm, not quite sure you understood the question? I've got the number of days already but I would like to get the hours and minutes too.

function getOverdueTime($sDate )
  {

       $currentDate = time();
    
        $sDate = strtotime(sDate );

	$secsBetween = ($sDate - $currentDate);
    
        $days = $secsBetween / 86400;
        $days = floor($days)+1;

	$hours = ($secsBetween % 86400) / 3600;
	$hours = floor($hours)+1;

	$mins = (($secsBetween % 86400) % 3600) / 60;
	$mins = floor($mins)+1;
       
        return $days.' day(s) '.$hours.' hour(s) '.$mins.' min(s) and ' .$secsBetween.' second(s)';
     
  }

 

Perhaps something like this?

function getOverdueTime($sDate )
  {

       $currentDate = time();
    
        $sDate = strtotime(sDate );

	$secsBetween = ($sDate - $currentDate);
    
        $days = $secsBetween / 86400;
        $days = floor($days)+1;

	$hours = ($secsBetween % 86400) / 3600;
	$hours = floor($hours)+1;

	$mins = (($secsBetween % 86400) % 3600) / 60;
	$mins = floor($mins)+1;
       
        return $days.' day(s) '.$hours.' hour(s) '.$mins.' min(s) and ' .$secsBetween.' second(s)';
     
  }

 

Perhaps something like this?

 

Hmm, that returns:

 

-15184 day(s) -22 hour(s) -21 min(s) and -1311978076 second(s)

 

:wtf:

Ah yeah, it's this line:

 

$secsBetween = ($sDate - $currentDate);

 

Change to:

 

$secsBetween = ($currentDate - $sDate);

 

Getting there lol. The days no longer works, even my original doesn't. It now returns: By the way the date I am passing in is 2011-08-05 09:00:00 so not sure the hours are correct either?!

 

15185 day(s) 23 hour(s) 25 min(s) and 1311978297 second(s)

function getOverdueString($dueDate, $currentDate = 'now', $formatString = '%r%dd %hh %im') {
    try {
        $a    = new DateTime($currentDate);
        $b    = new DateTime($dueDate);
        $diff = $a->diff($b);
        if ($diff instanceof DateInterval) {
            return $diff->format($formatString); // formats: (positive) 1d 1h 0m (negative) -1d 3h 0m
        }
    } catch (Exception $e) {}
    return '';
} // echo getOverdueString( '2011-08-05 09:00:00', '2011-08-05 08:30:00'); // 0d 0h 30m

 

 

The above function should be self-explanatory. It gives you complete control over the used format (the DateInterval format). Only the due date is required all other parameters are optional. So you could just write:

 

echo getOverdueString($dueDate);

 

If the date is invalid or it couldn't calculate a diff the output will be '' (maybe change that to FALSE?) Another option could be to just return the DateInterval object and go from there since it provides you with handy properties for even more control than format() does.

The above function should be self-explanatory. It gives you complete control over the used format (the DateInterval format). Only the due date is required all other parameters are optional. So you could just write:

 

echo getOverdueString($dueDate);

 

If the date is invalid or it couldn't calculate a diff the output will be '' (maybe change that to FALSE?) Another option could be to just return the DateInterval object and go from there since it provides you with handy properties for even more control than format() does.

 

Hi,

 

Thanks for your help, is this only valid using PHP 5.3 though? Unfortunately, the server only has PHP 5  >:(

 

I thought I was on the right path with my initial post but unsure why this doesn't work now. Do you have a method for PHP 5?

Below is some code from one of my tools on Online Wasteland. It's not doing exactly what you mentioned, but you should be able to easily adapt the code to do what you need.

 

    <?php
/* Function gets differences in seconds */
function timeDiff($firstTime,$lastTime) {		
	// perform subtraction to get the difference (in seconds) between times
	$timeDiff=$lastTime-$firstTime;

	// return the difference
	return $timeDiff;
}

// Get first/second timestamps
$first_timestamp = $this->input->post('first_timestamp');
$second_timestamp = $this->input->post('second_timestamp');

// Echo out their basic data
echo '<p>The first timestamp \'' . $first_timestamp . '\' converts to ' . date('m/d/Y h:i:s A', $first_timestamp) . ' and the second timestamp \'' . $second_timestamp . '\' converts to ' . date('m/d/Y h:i:s A', $second_timestamp) . '.</p>';

// Perform Conversion.  
$seconds = timeDiff($first_timestamp, $second_timestamp);
echo '<p>There are a total of ' . round($seconds) . ' seconds between Timestamp 1 and Timestamp 2.</p>';
echo '<p>There are a total of ' . round($seconds / 60) . ' minutes between Timestamp 1 and Timestamp 2.</p>';
echo '<p>There are a total of ' . round(($seconds / 60) / 1440) . ' days between Timestamp 1 and Timestamp 2.</p>';
echo '<p>There are a total of ' . round((($seconds / 60) / 1440) / 7) . ' weeks between Timestamp 1 and Timestamp 2.</p>';
echo '<p>There are a total of ' . round((((($seconds / 60) / 1440) / 7) / 30)) . ' months between Timestamp 1 and Timestamp 2.</p>';
echo '<p>The total breakdown of time from Timestamp 1 to Timestamp 2 is ';
$diff = $seconds;	
$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));

$hours   = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60)); 

$minuts  = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60); 

$seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60)); 
echo $years . ' Years, ' . $months . ' Months, ' . $days . ' Days, ' . $hours . ' Hours, ' . $minuts . ' Minutes, and ' . $seconds . ' Seconds.</p>';
?>

The code assumes it's in timestamp format. Just do the conversion to the date you want.  This code is also a little bloated, I wrote it in a hurry, I was

planning on refining the utility later. But it should help you get the basic idea to help figure out what you need.

I am not aware of any standard functions that mimic DateTime perfectly I have tested both strftime() and date() none of them got it correct date() f.e. returned 1 day 30 mins for 1800, that may be my bad either though not sure.

 

Here's an example that works like the DateTime function did.

 

function getOverdueString($dueDate, $currentDate = 'now', $formatString = '%s%dd %dh %dm') {
    $a = strtotime($dueDate);
    if ($a === FALSE || $a === -1/*<5.1*/) return FALSE;
    
    $b = strtotime($currentDate);
    if ($b === FALSE || $b === -1/*<5.1*/) return FALSE;
    
    $diff = $a - $b;
    $sign = $diff < 0 ? '-' : '';
    
    $diff = abs($diff);
    $days = floor($diff / 86400);
    $hrs  = ($diff % 86400) / 3600;
    $mnts = (($diff % 86400) % 3600) / 60;
    
    return sprintf($formatString, $sign, $days, $hrs, $mnts);
} // echo getOverdueString( '2011-08-05 09:00:00', '2011-08-05 08:30:00'); // 0d 0h 30m

Almost there! The following seems to work if I put the due date in the past e.g 29/07/2011 09:00:00 returns -1 day(s) -8 hour(s) -6 min(s) and -115607 second(s)

However, if I do a due date in the future it seems to add an additional day on e.g 31/07/2011 09:00:00 returns 1 day(s) 16 hour(s) 57 min(s) and 57412 second(s) - this should be 0 day(s) 16 hour(s) 57 min(s) and 57412 second(s) shouldn't it??

 

<?php

echo getOverdueTime("2011-07-31 09:00:00");

function getOverdueTime($sDate )
  {

        $currentDate = time();
    
        $sDate = strtotime($sDate );

$secsBetween = ($sDate - $currentDate);
    
        $days = $secsBetween / 86400;
        $days = floor($days)+1;

$hours = ($secsBetween % 86400) / 3600;

$hours = floor($hours)+1;

$mins = (($secsBetween % 86400) % 3600) / 60;

$mins = floor($mins)+1;
       
        return $days.' day(s) '.$hours.' hour(s) '.$mins.' min(s) and ' .$secsBetween.' second(s)';
     
  }
?>

I think this now works correctly. Can someone else please try it for me using dates in the past and future?

 

function getOverdueString($dueDate, $currentDate = 'now', $formatString = '%s%dd %dh %dm') {
    $a = strtotime($dueDate);
    if ($a === FALSE || $a === -1/*<5.1*/) return FALSE;
    
    $b = strtotime($currentDate);
    if ($b === FALSE || $b === -1/*<5.1*/) return FALSE;
    
    $diff = $a - $b;
    $sign = $diff < 0 ? '-' : '';
    
    $diff = abs($diff);
    $days = floor($diff / 86400);
    $hrs  = ($diff % 86400) / 3600;
    $mnts = (($diff % 86400) % 3600) / 60;
    
    return sprintf($formatString, $sign, $days, $hrs, $mnts);
} 

function getOverdueString($dueDate, $currentDate = 'now', $timezone = 'Europe/Brussels', $formatString = '%s%dd %dh %dm') {
    $old_timezone = date_default_timezone_get();
    date_default_timezone_set($timezone);
    
    $a = strtotime($dueDate);
    if ($a === FALSE || $a === -1/*<5.1*/) return FALSE;
    
    $b = strtotime($currentDate);
    if ($b === FALSE || $b === -1/*<5.1*/) return FALSE;
    
    date_default_timezone_set($old_timezone);
    
    $diff = $a - $b;
    $sign = $diff < 0 ? '-' : '';
    
    $diff = abs($diff);
    $days = floor($diff / 86400);
    $hrs  = floor(($diff % 86400) / 3600);
    $mnts = floor((($diff % 86400) % 3600) / 60);
    
    return sprintf($formatString, $sign, $days, $hrs, $mnts);
}

 

I have made a few adjustments:

 

1) added floor to $hrs and $mnts

2) added in timezone support since your customers will likely be in a different timezone so the overdue date should be calculated according to their timezone otherwise they would buy/rent your product and lose a few or lots of hours on the meter before overdue. So be sure to ask the timezone of your customer.

 

Proof-of-Concept:

// 'now' => 2011-07-31 8:16:00
print getOverdueString('2012-07-31 8:12:00').PHP_EOL; // 365d 23h 55m
print getOverdueString('2011-07-31 8:12:00').PHP_EOL; // -0d 0h 4m
print getOverdueString('2010-07-31 8:12:00').PHP_EOL; // -365d 0h 4m

 

Be sure to change Europe/Brussels with yours. You can find the supported timezones on php.net

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.