PHP: Calculate Real Differences Between Two Dates or Timestamps

I was using simple function to calculate difference between two dates and timestamps until I noticed, it’s not working correctly in long intervals. It’s very easy to calculate difference between two timestamps in seconds, but it’s much more complicated print difference in human readable format. The Internet can be found in a wide range of ways to do this thing, but as a rule they use a fixed amount of seconds for the year and the month. So if we calculate year with using 365 or 365.25 days and month using 30 or 31 then the difference is not accurate, because of leap years, DST (Daylight Saving Time) and so on.

Because of this problem, I decided to make a function (at least in the short testing) to return the right kind of differences between the UNIX timestamps and dates in human readable format. This function uses PHP strtotime function to calculate real differences and can handle leap years and DST. This function can also return Twitter like about texts with precision parameter.

PHP dateDiff function for calculating real differences between dates and UNIX timestamps

<?php
 
  // Set timezone
  date_default_timezone_set("UTC");
 
  // Time format is UNIX timestamp or
  // PHP strtotime compatible strings
  function dateDiff($time1, $time2, $precision = 6) {
    // If not numeric then convert texts to unix timestamps
    if (!is_int($time1)) {
      $time1 = strtotime($time1);
    }
    if (!is_int($time2)) {
      $time2 = strtotime($time2);
    }
 
    // If time1 is bigger than time2
    // Then swap time1 and time2
    if ($time1 > $time2) {
      $ttime = $time1;
      $time1 = $time2;
      $time2 = $ttime;
    }
 
    // Set up intervals and diffs arrays
    $intervals = array('year','month','day','hour','minute','second');
    $diffs = array();
 
    // Loop thru all intervals
    foreach ($intervals as $interval) {
      // Set default diff to 0
      $diffs[$interval] = 0;
      // Create temp time from time1 and interval
      $ttime = strtotime("+1 " . $interval, $time1);
      // Loop until temp time is smaller than time2
      while ($time2 >= $ttime) {
	$time1 = $ttime;
	$diffs[$interval]++;
	// Create new temp time from time1 and interval
	$ttime = strtotime("+1 " . $interval, $time1);
      }
    }
 
    $count = 0;
    $times = array();
    // Loop thru all diffs
    foreach ($diffs as $interval => $value) {
      // Break if we have needed precission
      if ($count >= $precision) {
	break;
      }
      // Add value and interval 
      // if value is bigger than 0
      if ($value > 0) {
	// Add s if value is not 1
	if ($value != 1) {
	  $interval .= "s";
	}
	// Add value and interval to times array
	$times[] = $value . " " . $interval;
	$count++;
      }
    }
 
    // Return string with times
    return implode(", ", $times);
  }
 
?>

dateDiff function example usage

strtotime examples:

echo dateDiff("2010-01-26", "2004-01-26") . "\n";
echo dateDiff("2006-04-12 12:30:00", "1987-04-12 12:30:01") . "\n";
echo dateDiff("now", "now +2 months") . "\n";
echo dateDiff("now", "now -6 year -2 months -10 days") . "\n";
echo dateDiff("2009-01-26", "2004-01-26 15:38:11") . "\n";

Output:

6 years
18 years, 11 months, 30 days, 23 hours, 59 minutes, 59 seconds
2 months
6 years, 2 months, 10 days
4 years, 11 months, 30 days, 8 hours, 21 minutes, 49 seconds

UNIX timestamp and precision examples

echo dateDiff(time(), time()-1000000, 1) . "\n";
echo dateDiff(time(), time()-1000000, 3) . "\n";
echo dateDiff(time(), time()-1000000, 6) . "\n";

Output:

11 days
11 days, 13 hours, 46 minutes
11 days, 13 hours, 46 minutes, 40 seconds

Converting text format back to UNIX timestamp example

$time1 = time();
$time2 = $time1-10000000;
echo $diff = dateDiff($time1, $time2) . "\n";
echo $time1 . "\n";
echo strtotime(" +".$diff, $time2) . "\n";

Output:

3 months, 23 days, 17 hours, 46 minutes, 40 seconds
1264514564
1264514564
Follow If Not True Then False Updates!

179 Comments

  1. Hey JR, been a while since I’ve posted here… any way, I was wondering if you could help me with something. Below is the code used on my site and I was wondering if you could tell me what needs to be altered to number_format() the days so come the 3rd yr you wouldn’t see 1095 but instead would see 1,095.

    Thx JR !

    // Time format is UNIX timestamp or
    // PHP strtotime compatible strings
    function dateDiff($time1, $time2, $precision = 4) {
    // If not numeric then convert texts to unix timestamps
    if (!is_int($time1)) {
    $time1 = strtotime($time1);
    }
    if (!is_int($time2)) {
    $time2 = strtotime($time2);
    }

    // If time1 is bigger than time2
    // Then swap time1 and time2
    if ($time1 > $time2) {
    $ttime = $time1;
    $time1 = $time2;
    $time2 = $ttime;
    }

    // Set up intervals and diffs arrays
    $intervals = array('Year', 'Day', 'Hour', 'Minute');
    $interval_names = array('Year' => 'Yr', 'Day' => 'Day', 'Hour' => 'Hr', 'Minute' => 'Min');
    $diffs = array();

    // Loop thru all intervals
    foreach ($intervals as $interval) {
    // Set default diff to 0
    $diffs[$interval] = 0;
    // Create temp time from time1 and interval
    $ttime = strtotime("+1" . $interval, $time1);
    // Loop until temp time is smaller than time2
    while ($time2 >= $ttime) {
    $time1 = $ttime;
    $diffs[$interval]++;
    // Create new temp time from time1 and interval
    $ttime = strtotime("+1" . $interval, $time1);
    }
    }

    $count = 0;
    $times = array();
    // Loop thru all diffs
    foreach ($diffs as $interval => $value) {
    // Break if we have needed precission
    if ($count >= $precision) {
    break;
    }
    // Add value and interval
    // if value is bigger than 0
    if ($value > 0) {
    // Add if value is not 1
    if ($value != 1) {
    $interval = $interval_names[$interval] . "s";
    }
    else {
    $interval = $interval_names[$interval];
    }
    // Add value and interval to times array
    $times[] = $value . " " . $interval;
    $count++;
    }
    }

    // Return string with times
    return implode(", ", $times);
    }

    // echo dateDiff(1267074000, time(), 4) . "\n";

    function addOrdinalSuffix($number) {
    if (in_array(($number % 100),array(11,12,13))){
    return $number.'th';
    }
    else {
    switch (($number % 10)) {
    case 1:
    return $number.'st';
    break;
    case 2:
    return $number.'nd';
    break;
    case 3:
    return $number.'rd';
    break;
    default:
    return $number.'th';
    break;
    }
    }
    }

    $birthday_date = '2010-02-25';
    $current_date = date('Y-m-d');

    list($birthday_year, $birthday_month, $birthday_day) = explode("-", $birthday_date);
    list($current_year, $current_month, $current_day) = explode("-", $current_date);

    if ($birthday_month == $current_month && $birthday_day == $current_day) {
    echo 'Happy ', addOrdinalSuffix($current_year - $birthday_year), ' B-Day myu2sig.com !';
    echo "\n";
    }

    else {echo dateDiff(1267074000, time(), 4) . "\n";}

    • Hi again Andy :)

      I don’t fully understand that what you want to do because I can’t find number_format() function in your code.

      Could you please try to explain a bit more detailed, so I can try to help you…

  2. number_format() is not in the code, what I am saying is that I want to make the days figured be encased by it.

    So come the 3rd yr you wouldn’t see 1095 but instead would see 1,095.

    As the code stands in it’s current format, shold 3 yrs go by you would see 1095 and thats just ugly to me.

    Now do you get it ?

    • Hi Andy,

      Try following:

      // Change following line
      $times[] = $value . " " . $interval;
       
      // To
      $times[] = number_format($value, 0, '.', ',') . " " . $interval;
  3. That did it, thx.

    • Excellent! :D

  4. @itsgreen – Anything prior to 1970/71 needs to be formatted like a negative number.

    ex. -2204201921

    That should allow this “script” to function with any date prior to 1970/71.

  5. @itsgreen – Not sure if how you would do it but you could possibly code the “script” to add the – to the beginning of any timestamps that are prior to 1970 since in your case it sounds like your full on auto and not doing anything on a case by case basis.

  6. @itsgreen and @andy

    This function is designed to work only with UNIX timestamps, it’s reason why this is not working with anything prior 1970.


    What is the UNIX time stamp?

    The UNIX time stamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970. Therefore, the unix time stamp is merely the number of seconds between a particular date and the Unix Epoch. This is very useful to computer systems for tracking and sorting dated information in dynamic and distributed applications both online and client side.

  7. @JR – In regards to my comments to itsgreen, your script does accurately work with dates / timestamps prior to 1970. I tested this with something from the 1900′s and it worked great. You just need the – at the beginning of the timestamps to say ok, this is before 1970.

    This is what I used to get a timestamp from the 1900′s which I then plugged in to your system and it worked out just fine.

    Epoch & Unix Timestamp Conversion Tools

  8. very nice read and function works like charm, thank you

  9. Thx for this script. I am using it to show how soon an event is coming up, but when it passes it should show “Overdue”. Any ideas?

  10. I figured it out:

    // if same day
    if ($time1 == $time2) {
    echo “TODAY”;
    }

    // if past
    if ($time1 $time2) {
    $ttime = $time1;
    $time1 = $time2;
    $time2 = $ttime;
    }

  11. // if same day
    if ($time1 == $time2) { echo “TODAY”; }

    // if past
    if ($time1 $time2) {
    $ttime = $time1;
    $time1 = $time2;
    $time2 = $ttime;
    }

  12. Hello
    I as well like your dateDiff function thank you for sharing this function

    I am using your above function on a timesheet db application where I calculate the total of the time worked ( time IN 7:00 AM time Out 5: 00 PM )

    your function displays the time diff as expectected when displaying one timesheet or the time of single timesheets.
    I display the last two weeks timesheets and I would need the total sum of worked time displayed. I wonder if I can modify your function maybe with a staic value


    function dateDiff($time1, $time2, $precision = 6) {
    static $SumTotalTime;

    $times[] = $value . ” ” . $interval;
    $SumTotalTime = ($SumTotalTime + $value);
    $count++;

    can someone please point me in the right direction how I could display the total time processed with the function from the page

    thank you

    • Hi Vincent,

      Glad to hear that you like dateDiff function.

      In your case, is certainly an easier way to calculate the time between the two timestamp. I wrote quick class for you. If I understand correctly, what you’re doing, so the following example might work.

      TimestampCalc class

      class TimestampCalc {
      	private $total_seconds;
       
      	public function __construct() {
      		$this->total_seconds = 0;
      	}
       
      	public function resetTotal() {
      		$this->total_seconds = 0;
      	}
       
      	// Time format is UNIX timestamp or
      	// PHP strtotime compatible strings
      	public function addTimeDiff($time1, $time2) {
      		// If not numeric then convert texts to unix timestamps
      		if (!is_int($time1)) {
      			$time1 = strtotime($time1);
      		}
      		if (!is_int($time2)) {
      			$time2 = strtotime($time2);
      		}
       
      		// If time1 is bigger than time2
      		// Then swap time1 and time2
      		if ($time1 > $time2) {
      			$ttime = $time1;
      			$time1 = $time2;
      			$time2 = $ttime;
      		}
       
      		$this->total_seconds += ($time2 - $time1);
      	}
       
      	public function getPlainTotal() {
      		return $this->total_seconds;
      	}
       
      	public function getFormattedTotal() {
      		$diffs = array();
      		$diffs['hour'] =  floor ($this->total_seconds / (60 * 60));
      		// extract minutes
      		$minutes = $this->total_seconds % (60 * 60);
      		$diffs['minute'] = floor ($minutes / 60);
      		// extract seconds
      		$seconds = $minutes % 60;
          		$diffs['second'] = $seconds % 60;
       
      		$count = 0;
      		$times = array();
      		// Loop thru all diffs
      		foreach ($diffs as $interval => $value) {
      			// Add value and interval 
      			// if value is bigger than 0
      			if ($value > 0) {
      				// Add s if value is not 1
      				if ($value != 1) {
      					$interval .= "s";
      				}
      				// Add value and interval to times array
      				$times[] = $value . " " . $interval;
      				$count++;
      			}
      		}
      		// Return string with times
      		return implode(", ", $times);
      	}
      }

      Example usage

      $tc = new TimestampCalc();
       
      // Example1 times
      $tc->addTimeDiff("2011-04-08 08:15:00", "2011-04-08 12:45:00");
      $tc->addTimeDiff("2011-04-09 06:35:00", "2011-04-09 16:25:00");
      $tc->addTimeDiff("2011-04-10 07:45:00", "2011-04-10 14:30:00");
       
      // Example1 print
      echo "Example1:\n";
      echo $tc->getPlainTotal() . " seconds\n";
      echo $tc->getFormattedTotal() . "\n";
       
      $tc->resetTotal();
       
      // Example2 times
      $tc->addTimeDiff("2011-04-08 09:11:47", "2011-04-08 17:42:41");
      $tc->addTimeDiff("2011-04-09 08:38:17", "2011-04-09 16:31:28");
      $tc->addTimeDiff("2011-04-10 06:44:01", "2011-04-10 14:33:32");
       
      // Example2 print
      echo "\nExample2:\n";
      echo $tc->getPlainTotal() . " seconds\n";
      echo $tc->getFormattedTotal() . "\n";

      Output:

      Example1:
      75900 seconds
      21 hours, 5 minutes
      
      Example2:
      87216 seconds
      24 hours, 13 minutes, 36 seconds
      
  13. Dear Jr

    Your class works but i think you maybe miss understood my goal

    when displaying one time sheet your function and now your class works as expected ..

    MY DB Tbl. TimeIN 08:00AM TimeOut: 05:00PM
    I would display under the time sheet that the employee worked 9 hrs

    But I as well would like to display the total hours and min worked when multiple timesheets are selected .. .

    let me show you some code :

    while($get_employee_sheet_data = mysql_fetch_array($check_employee_timeSheets)) {
    $EmplSheetID = $get_employee_sheet_data['TimeSheetID'];
    $EmplSheetDate =$get_employee_sheet_data['TimeSheetDate'];
    $EmplSheetJobID = $get_employee_sheet_data['TimeSheetJobTitleID'];
    $EmplSheetJobTitle = $get_employee_sheet_data['TimeSheetJobTitle'];
    $EmplSheetIn = $get_employee_sheet_data['TimeSheetTimeIn'];
    $EmplSheetOut = $get_employee_sheet_data['TimeSheetTimeOut'];
    $tc = new TimestampCalc();
    $tc->addTimeDiff($EmplSheetIn, $EmplSheetOut);

    echo ““. $EmplSheetDate .” “. $EmplSheetJobTitle .” (“. $tc->getFormattedTotal() .”)

    ….

    the above recordset shows the time worked of one record, just now I would need the total times calculated by your function so I have a total of the selected recordset exsample 10 timesheets etc.

    thank you for your input and smarts

    • Hi again Vincent,

      Actually, I understood what you wanted to do, but only partially. :) Example works for collecting total time and returns it as formatted, but can’t return every added time as formatted. So let’s try again:

      New version of TimestampCalc class

      class TimestampCalc {
      	private $total_seconds;
       
      	public function __construct() {
      		$this->resetTotal();
      	}
       
      	// Reset total time
      	public function resetTotal() {
      		$this->total_seconds = 0;
      	}
       
      	// Time format is UNIX timestamp or
      	// PHP strtotime compatible strings
      	// Returns formatted time
      	public function addTimeDiff($time1, $time2) {
      		// If not numeric then convert texts to unix timestamps
      		if (!is_int($time1)) {
      			$time1 = strtotime($time1);
      		}
      		if (!is_int($time2)) {
      			$time2 = strtotime($time2);
      		}
       
      		// If time1 is bigger than time2
      		// Then swap time1 and time2
      		if ($time1 > $time2) {
      			$ttime = $time1;
      			$time1 = $time2;
      			$time2 = $ttime;
      		}
       
      		$time = ($time2 - $time1);
       
      		$this->total_seconds += $time;
       
      		return $this->formatTime($time);
      	}
       
      	// Returns plain total time
      	public function getPlainTotal() {
      		return $this->total_seconds;
      	}
       
      	// Returns formatted total time
      	public function getFormattedTotal() {
      		return $this->formatTime($this->total_seconds);
      	}
       
      	private function formatTime($total_seconds) {
      		$diffs = array();
      		$diffs['hour'] =  floor ($total_seconds / (60 * 60));
      		// extract minutes
      		$minutes = $total_seconds % (60 * 60);
      		$diffs['minute'] = floor ($minutes / 60);
      		// extract seconds
      		$seconds = $minutes % 60;
          	$diffs['second'] = $seconds % 60;
       
      		$count = 0;
      		$times = array();
      		// Loop thru all diffs
      		foreach ($diffs as $interval => $value) {
      			// Add value and interval 
      			// if value is bigger than 0
      			if ($value > 0) {
      				// Add s if value is not 1
      				if ($value != 1) {
      					$interval .= "s";
      				}
      				// Add value and interval to times array
      				$times[] = $value . " " . $interval;
      				$count++;
      			}
      		}
      		// Return string with times
      		return implode(", ", $times);
      	}
      }

      Example usage

      $tc = new TimestampCalc();
       
      // Example1 print
      echo "Example1:\n";
      // Example1 times
      echo $tc->addTimeDiff("2011-04-08 08:15:00", "2011-04-08 12:45:00") . "\n";
      echo $tc->addTimeDiff("2011-04-09 06:35:00", "2011-04-09 16:25:00") . "\n";
      echo $tc->addTimeDiff("2011-04-10 07:45:00", "2011-04-10 14:30:00") . "\n";
       
      echo "Plain total: " . $tc->getPlainTotal() . " seconds\n";
      echo "Formatted total: " . $tc->getFormattedTotal() . "\n";
       
      $tc->resetTotal();
       
      // Example2 print
      echo "\nExample2:\n";
       
      // Example2 times
      echo $tc->addTimeDiff("2011-04-08 09:11:47", "2011-04-08 17:42:41") . "\n";
      echo $tc->addTimeDiff("2011-04-09 08:38:17", "2011-04-09 16:31:28") . "\n";
      echo $tc->addTimeDiff("2011-04-10 06:44:01", "2011-04-10 14:33:32") . "\n";
       
      echo "Plain total: " . $tc->getPlainTotal() . " seconds\n";
      echo "Formatted total: " . $tc->getFormattedTotal() . "\n";

      Output

      Example1:
      4 hours, 30 minutes
      9 hours, 50 minutes
      6 hours, 45 minutes
      Plain total: 75900 seconds
      Formatted total: 21 hours, 5 minutes
      
      Example2:
      8 hours, 30 minutes, 54 seconds
      7 hours, 53 minutes, 11 seconds
      7 hours, 49 minutes, 31 seconds
      Plain total: 87216 seconds
      Formatted total: 24 hours, 13 minutes, 36 seconds
      

      Usage on your code

      // Create class just once
      $tc = new TimestampCalc();
       
      // ....
       
      while($get_employee_sheet_data = mysql_fetch_array($check_employee_timeSheets)) {
      	$EmplSheetID = $get_employee_sheet_data['TimeSheetID'];
      	$EmplSheetDate =$get_employee_sheet_data['TimeSheetDate'];
      	$EmplSheetJobID = $get_employee_sheet_data['TimeSheetJobTitleID'];
      	$EmplSheetJobTitle = $get_employee_sheet_data['TimeSheetJobTitle'];
      	$EmplSheetIn = $get_employee_sheet_data['TimeSheetTimeIn'];
      	$EmplSheetOut = $get_employee_sheet_data['TimeSheetTimeOut'];
       
      	// addTimeDiff function returns formatted time
      	$formattedTime = $tc->addTimeDiff($EmplSheetIn, $EmplSheetOut);
       
      	// Print formatted time
      	echo "". $EmplSheetDate ." ". $EmplSheetJobTitle ." (". $formattedTime .")";
       
      }
       
      // ....
       
      // Loop more timeSheets or something
       
      // Print formatted total time from all added times
      echo "Total: " . $tc->getFormattedTotal() . "\n";
  14. Jr thank you for your time and the way of writing the above class, It works well here for my timesheet application.
    If you dont mind I would like to keep in touch with you.

    Thank you again

  15. I have to ask you another question what is in regarding the time difference

    I am saving the above times as a varchar in the timesheet table ( 07:00 AM )
    I had this issue that the date type is not so practicly in my timesheet application

    it works very well now to calculate the times of the timesheet tx to your class ..

    However Jr bevore entering new timesheet data into the table I have to check if the times are overlapping with already a saved timesheet. I wonder if you would again direct me in the right direction, i know if the times are saved as date time field i would have a query similar to seee below:

    how would you write the timesheet overlap check because my fields are strings

    Timesheet Add

    }else{
    $strSql=”SELECT * FROM `TimesheetTbl` WHERE `TimeSheetTimeIN` between ‘$strSheetTimeIN’ AND ‘$strSheetTimeOut’ OR `TimeSheetTimeOut`
    between ‘$strSheetTimeIN’ AND ‘$strSheetTimeOut’ AND `TimeSheetDate` = ‘$strTimeSheetDate’ AND `TimeSheetUserID` = $EmpldbID”;
    $check_time_sheet = mysql_query($strSql);
    echo $strSql;
    if(mysql_num_rows($check_time_sheet) != 0){
    $final_report.=”found a recorded timesheet with overlapping times!”;
    }else{
    ….

    I wonder should I query first the existing times and format them or is it possible to check the overlapp via sql

  16. Jr
    I been searching online and testing so much with no success to check the times stored as string in the db for overlapping times . I as well asked in other forums and they say its not possible . I still dont think so . there must be a way of converting the string times on the fly in the sql or maybe in an array when I retrieve the existing times from a recordset.

    Jr. If you think its not possible i change the db field type to a date field but it would be so much better if I can leave them as varchar and still validate the input

    thanks for your input

  17. Hi again Vincent,

    Nice to hear that my class work on your timesheet application. :)

    I’ve been a little busy, but here’s my thoughts to the problem.

    First, the best way to store the date and time is of course the database fields that are real date and time types.

    But I think that your situation is not impossible. You could use MySQL STR_TO_DATE function to convert your varchar type dates and times to real MySQL dates and times.

    STR_TO_DATE Example usage (Linux date format converted to MySQL datetime)

    mysql> SELECT STR_TO_DATE('Fri Apr 15 10:13:03 2011', '%a %b %d %H:%i:%s %Y') AS datetime;
    +---------------------+
    | datetime            |
    +---------------------+
    | 2011-04-15 10:13:03 |
    +---------------------+
    1 ROW IN SET (0.05 sec)

    You could use this method for times and dates separated or concatenate date and time to one varchar and convert it to mysql datetime. This is actually inverse DATE_FORMAT function.

    More info from MySQL str_to_date manual and MySQL date_format manual.

  18. Dear Jr

    I have an issue with your class and I can not find my error. Your class works everywhere very fine in my application. Today was working on the payroll sytem of my timesheet application. I used your class in the same manner as i did on other screens withhn my app. now when I want to display the times it looks like:
    (362201 hours, 45 minutes) (362207 hours, 45 minutes) (362213 hours, 30 minutes)
    on a different page with the same times it comes out normal:
    (3 hours, 15 minutes) (4 hours, 45 minutes) (4 hours, 45 minutes)
    Can you explain and point me to a solution?
    thank you

    • Hi again Vincent,

      It is very hard to say and debug because I don’t know your code exactly where you are using my class.

  19. WOOOO!!!! I was stuck on this problem for a while. Thanks for the help. :)

  20. On one page is working fine and on the other with the same times it runs different?

    here is the code of the page where it gives me the wrong format, time_eader.php holds only your class and I include it on a other pages and the times work well!

    >>>>> php
    include(‘time_reader.php’); <<<php

    <<<php

    $strDate = trim($_POST['txtDate']);
    $strDate2 = trim($_POST['txtDate2']);

    $strUsr = $_POST['chkUsrInclude'];
    $strQueryAtt=" WHERE TimeSheetFiled 1 “;
    $strQueryOrder = ” ORDER BY TimeSheetDate DESC ” ;
    if ((strlen($strDate) > 0) AND (strlen($strDate2) =’”. $strDate .”‘ “;
    }
    if ((strlen($strDate2) >0) AND (strlen($strDate) < 1)){
    $strQueryAtt .=" AND TimeSheetDate <= '". $strDate2 ."' ";
    }

    if (($strDate2 “”) AND ($strDate “”)){
    $strQueryAtt .=” AND TimeSheetDate BETWEEN ‘”. $strDate .”‘ AND ‘”. $strDate2 .”‘”;
    }
    $n=count($strUsr);
    if ($n> 0) {
    for ($i=0; $i

    Start:
    <input name="txtDate" type="text" id="txtDate" size="10" maxlength="12" readonly="True" value="” onclick=”scwShow(scwID(‘txtDate’),event);” style=”cursor:hand” />

    End:
    <input name="txtDate2" type="text" id="txtDate2" size="10" maxlength="12" readonly="True" value="” onclick=”scwShow(scwID(‘txtDate2′),event);” style=”cursor:hand”/>

    <<php $strQuery = "SELECT DISTINCT TimeSheetUserID, TimeSheetUsrName FROM `TimesheetTbl` ". $strQueryAtt . " ";
    $check_employees_in_Sheets = mysql_query($strQuery) or die(mysql_error());
    if(mysql_num_rows($check_employees_in_Sheets) == 0){
    echo "no records found in range”;
    }else{ ?>

    <<<php while($get_employee_sheet_data = mysql_fetch_array($check_employees_in_Sheets)) {
    $EmplName = $get_employee_sheet_data['TimeSheetUsrName'];
    $EmplID = $get_employee_sheet_data['TimeSheetUserID'];
    echo "”. $EmplName . “”;
    }
    ?>

    <?php
    echo "”;
    echo ” “;
    echo ” “;
    $strQuery = “SELECT * FROM `TimesheetTbl` “. $strQueryAtt . ” “. $strQueryOrder .”";
    $rs_empl_filter_Sheets = mysql_query($strQuery) or die(mysql_error());
    $i=mysql_num_rows($rs_empl_filter_Sheets);
    if($i == 0){
    echo “no timesheet records found in range”;
    }else{

    echo “”;
    echo “Timesheets: “. $i .”";
    echo “”;
    echo ” “;
    echo ” “;
    echo ” Date”;
    echo ” Job”;
    echo ” Times”;
    echo ” File”;
    echo ” “;
    echo ” “;
    $tc = new TimestampCalc();
    while($get_employee_sheet_data = mysql_fetch_array($rs_empl_filter_Sheets)) {
    $EmplSheetID = $get_employee_sheet_data['TimeSheetID'];
    $EmplSheetDate =$get_employee_sheet_data['TimeSheetDate'];
    $EmplSheetJobID = $get_employee_sheet_data['TimeSheetJobTitleID'];
    $EmplSheetJobTitle = $get_employee_sheet_data['TimeSheetJobTitle'];
    $EmplSheetIn = $get_employee_sheet_data['TimeSheetTimeIn'];
    $EmplSheetOut = $get_employee_sheet_data['TimeSheetTimeOut'];
    $EmplSheetIn2 = $get_employee_sheet_data['TimeSheetTimeIn2'];
    $EmplSheetOut2 = $get_employee_sheet_data['TimeSheetTimeOut2'];
    $EmplSheetIn3 = $get_employee_sheet_data['TimeSheetTimeIn3'];
    $EmplSheetOut3 = $get_employee_sheet_data['TimeSheetTimeOut3'];
    $formattedTime = $tc->addTimeDiff($EmplSheetIn, $EmplSheetOut);
    $formattedTime2 = $tc->addTimeDiff($EmplSheetIn2, $EmplSheetOut2);
    $formattedTime3 = $tc->addTimeDiff($EmplSheetIn3, $EmplSheetOut3);
    $n_total_i = $tc->addTimeDiff($EmplSheetIn,$EmplSheetOut);
    $n_total_i_2 = $tc->addTimeDiff($EmplSheetIn2,$EmplSheetOut2);
    $n_total_i_3 = $tc->addTimeDiff($EmplSheetIn3,$EmplSheetOut3);

    echo “”;
    echo “”;
    echo ” “;
    echo ” “. $EmplSheetDate .”“;
    echo ” “. $EmplSheetJobTitle .”";
    echo ” (“. $n_total_i .”)”;
    if (strlen($n_total_i_2) >0) {
    echo ” (“. $n_total_i_2 .”) “;
    }
    if (strlen($n_total_i_3) >0) {
    echo ” (“. $n_total_i_3 .”) “;
    }
    echo “”;
    echo ” “;
    echo ” “;
    echo ” “;
    echo ” “;
    echo ” “;
    echo ” “;
    } // timesheets
    echo ” “;
    echo ” Total Time: “. $tc->getFormattedTotal() .”";
    }
    echo “”;
    echo “”;
    echo “”;
    >>>php

    PS: each timesheet can hold multiple times.
    thanks for your smarts

  21. Jr I found the bug …. .. how strange is this … the only diff on the above page is my sql query what uses select * … I just changed the query and added all the fields names into the query

    select TimeSheetTimeIn, TimeSheetTimeOut, TimeSheetTimeIn2, TimeSheetTimeOut2, TimeSheetTimeIn3, TimeSheetTimeOut3,
    TimeSheetJobTitle, TimeSheetJobTitleID, TimeSheetJobDescription, TimeSheetDate, TimeSheetFiled FROM `TimesheetTbl` ….

    and voila your times are formated correctly

    • Hi Vincent,

      And nice to hear that you get it working!

  22. JR, great blog post. Just what I wanted, thanks!

    I just have one question about it… is there any way to exclude certain hours from this count? I’m trying to use this script in an environment that counts working hours, and such it should only count 9 out of 24 hours per day (9 AM to 6 PM).
    Unfortunately this goes above my head as far as my PHP/function knowledge goes. Any chance you can assist me on this?

    • Hi Thomas,

      Actually this is not best approach on your case. Could you just loop through your working days and count every days hours?

      I think you should check PHP: Loop through dates (from date to date) with strtotime() function post.

      Please feel free to ask for further guidance, if you need some more?

      • Well, my situation is as follows:
        I have four variables, $date, $time, $enddate and $endtime. These come from a MySQL database and contain stuff like “2011-05-18″ and “13:39:00″ for $date and $time, and “2011-06-12″ and “16:05:00″ for $enddate and $endtime.

        What I want to do here is calculate the hours between those dates, but without weekends and non-working hours (6PM to 9 AM, evening). How would this apply to the loop bit?

        • This is slightly more problematic than what I thought of first.

          So you have to get first day 13:39 to 18:00 and next days 9:00 to 18:00 and last day 9:00 to 16:05 weekends excluded?

          • Yes, like that. I should count all the time that has been passed between time A, date B and time X, date Z. Excluding non-working hours (15 hours each day – 6PM to 9AM) and weekends.

          • So something like from Friday 4:35PM to Tuesday 11:10AM should result in 13 hours 45 minutes.

            • Hi again Thomas,

              So you mean 12 hours 45 minutes?

              1 h 25 min (Friday)
              9 h (Monday)
              2 h 10 min (Tuesday)
              
              12 h 35 minutes (total)
              

              But yes here is example code which should work for you. I wrote this class once for Vincent, but reuse it here now… :)

              <?php	
               
              	class TimestampCalc {
              		private $total_seconds;
               
              		public function __construct() {
              			$this->resetTotal();
              		}
               
              		// Reset total time
              		public function resetTotal() {
              			$this->total_seconds = 0;
              		}
               
              		// Time format is UNIX timestamp or
              		// PHP strtotime compatible strings
              		// Returns formatted time
              		public function addTimeDiff($time1, $time2) {
              			// If not numeric then convert texts to unix timestamps
              			if (!is_int($time1)) {
              				$time1 = strtotime($time1);
              			}
              			if (!is_int($time2)) {
              				$time2 = strtotime($time2);
              			}
               
              			// If time1 is bigger than time2
              			// Then swap time1 and time2
              			if ($time1 > $time2) {
              				$ttime = $time1;
              				$time1 = $time2;
              				$time2 = $ttime;
              			}
               
              			$time = ($time2 - $time1);
               
              			$this->total_seconds += $time;
               
              			return $time;
              		}
               
              		// Returns plain total time
              		public function getPlainTotal() {
              			return $this->total_seconds;
              		}
               
              		// Returns formatted total time
              		public function getFormattedTotal() {
              			return $this->formatTime($this->total_seconds);
              		}
               
              		private function formatTime($total_seconds) {
              			$diffs = array();
              			$diffs['hour'] =  floor ($total_seconds / (60 * 60));
              			// extract minutes
              			$minutes = $total_seconds % (60 * 60);
              			$diffs['minute'] = floor ($minutes / 60);
              			// extract seconds
              			$seconds = $minutes % 60;
              	    		$diffs['second'] = $seconds % 60;
               
              			$count = 0;
              			$times = array();
              			// Loop thru all diffs
              			foreach ($diffs as $interval => $value) {
              				// Add value and interval 
              				// if value is bigger than 0
              				if ($value > 0) {
              					// Add s if value is not 1
              					if ($value != 1) {
              						$interval .= "s";
              					}
              					// Add value and interval to times array
              					$times[] = $value . " " . $interval;
              					$count++;
              				}
              			}
              			// Return string with times
              			return implode(", ", $times);
              		}
              	}
               
               
              	// Set timezone
              	date_default_timezone_set('UTC');
               
              	$ts_calc = new TimestampCalc();
               
              	// Initial info
              	$working_day_start_time = '09:00:00';
              	$working_day_end_time = '18:00:00';
              	$exclude_days = array('Sat', 'Sun');
              	$debug = true;
              	$line_break = "\n";
               
              	// Start date
              	//$date = '2011-05-18';
              	$date = '2011-06-17';
              	// Start time
              	//$time = '13:39:00';
              	$time = '4:35 PM';
               
              	// End date
              	//$end_date = '2011-06-12';
              	$end_date = '2011-06-21';
              	// End time
              	//$end_time = '16:05:00';
              	$end_time = '11:10 AM';
               
              	// Special handling for start date and time
              	if (!in_array(date('D', strtotime($date)), $exclude_days)) {
              		$t = $ts_calc->addTimeDiff($date . " " . $time, $date . " " . $working_day_end_time);
              		if ($debug) {
              			echo $date, " is ", date('D', strtotime($date)), ', working time ', $t, " seconds", $line_break;
              		}
              	}
               
              	$date = date("Y-m-d", strtotime("+1 day", strtotime($date)));
              	while (strtotime($date) < strtotime($end_date)) {
              		if (!in_array(date('D', strtotime($date)), $exclude_days)) {
              			$t = $ts_calc->addTimeDiff($date . " " . $working_day_start_time, $date . " " . $working_day_end_time);
              			if ($debug) {
              				echo $date, " is ", date('D', strtotime($date)), ', working time ', $t, " seconds", $line_break;
              			}
              		}
              		$date = date("Y-m-d", strtotime("+1 day", strtotime($date)));
              	}
               
              	// Special handling for start date and time
              	if (!in_array(date('D', strtotime($end_date)), $exclude_days)) {
              		$t = $ts_calc->addTimeDiff($end_date . " " . $working_day_start_time, $date . " " . $end_time);
              		if ($debug) {
              			echo $date, " is ", date('D', strtotime($date)), ', working time ', $t, " seconds", $line_break;
              		}
              	}
               
              	echo $line_break, "Total time ", $ts_calc->getFormattedTotal(), $line_break;
               
              ?>

              Output, when debug is true

              2011-06-17 is Fri, working time 5100 seconds
              2011-06-20 is Mon, working time 32400 seconds
              2011-06-21 is Tue, working time 7800 seconds
              
              Total time 12 hours, 35 minutes
              

              Earlier example case output “2011-05-18 13:39:00″ to “2011-06-12 16:05:00″ (note this end date is Sunday)

              2011-05-18 is Wed, working time 15660 seconds
              2011-05-19 is Thu, working time 32400 seconds
              2011-05-20 is Fri, working time 32400 seconds
              2011-05-23 is Mon, working time 32400 seconds
              2011-05-24 is Tue, working time 32400 seconds
              2011-05-25 is Wed, working time 32400 seconds
              2011-05-26 is Thu, working time 32400 seconds
              2011-05-27 is Fri, working time 32400 seconds
              2011-05-30 is Mon, working time 32400 seconds
              2011-05-31 is Tue, working time 32400 seconds
              2011-06-01 is Wed, working time 32400 seconds
              2011-06-02 is Thu, working time 32400 seconds
              2011-06-03 is Fri, working time 32400 seconds
              2011-06-06 is Mon, working time 32400 seconds
              2011-06-07 is Tue, working time 32400 seconds
              2011-06-08 is Wed, working time 32400 seconds
              2011-06-09 is Thu, working time 32400 seconds
              2011-06-10 is Fri, working time 32400 seconds
              
              Total time 157 hours, 21 minutes
              

              I tested this code on Linux command line, so I use “\n” as a line break. If you test this on browser then change line break to

              $line_break = "";

              This code is not the most “polished” alternative, but should work at least on the basis of quick testing. :) Of course you could copy idea and make this code to fit your own code ;)

              Please let me know, if you have some problems, with this?

  23. Sorry for the late response.
    With some small modifications it worked great, thanks very much!

    But how would I be able to put the result in a hh:mm:ss format? That would make it perfect ;)

    • Hi Thomas,

      Nice to hear that it worked for you. :)

      Try to replace timeFormat function with following:

      private function formatTime($total_seconds) {
      	$times = array();
      	$times['hour'] =  str_pad(floor($total_seconds / (60 * 60)), 2, "0");
      	// extract minutes
      	$minutes = $total_seconds % (60 * 60);
      	$times['minute'] = str_pad(floor($minutes / 60), 2, "0");
      	// extract seconds
      	$seconds = $minutes % 60;
      	$times['second'] = str_pad($seconds % 60, 2, "0");
       
      	// Return string with times
      	return implode(":", $times);
      }

      It should work! ;)

  24. Hi,

    I read all the comments + check all the codes but its too complicated for me as I am new.

    I want the time diff between time now + $datetime (stored value in sql)

    i have 2 variables
    1. $datetime — stored timestamps in sql
    2. time(); — current date and time stamps

    output will be: 20 sec. ago or 1 hrs. ago and after 24 hrs. 1 day ago

    how so i get these value? IF you need full code, i can send you or will post here.

    • Hi,

      This original function should work for your case normally just use it like:

      echo dateDiff(time(), $datetime_from_mysql, 1);

      Let me know, if you have some problems with this.

  25. Jr,
    I would like to first thank you for all of the help that you have been providing to others here. It is not often that one human will go out of his or her way in the ways that you have.

    I have a small issue and I am sure that it is related to way to many hours behind the keyboard. The issue is that I am constantly being returned the same incorrect date no matter what the “previous” date is.

    For Example:

    echo time() . " - " . $row[logonDateTime] . "";
    echo "difference is " . (time() - $row['logonDateTime']) . "";
    echo time() . " - " . $row[logonDateTime] . "";
    echo "difference is " . (time() - $row['logoffDateTime']) . "";

    OUTPUT:

    1313117467 - 1313053080
    difference is 64387
    1313117467 - 1313053080
    difference is 62827

    How ever when I run it through your OP function like:


    $lastLogon = dateDiff(time(), $row[logonDateTime]);
    echo $lastLogon . "";
    $lastLogoff = dateDiff(time(), $row[logoffDateTime]);
    echo $lastLogoff . "";

    The result is always (regardless of a change in logonDateTime or logoffDateTime)

    41 years, 7 months, 11 days, 2 hours, 53 minutes, 51 seconds
    41 years, 7 months, 11 days, 2 hours, 53 minutes, 51 seconds

    As you can see above when i subtract each of those time stamps from the current time(), A true representation of how many seconds is represented. I am unable to figure out why running it though your function would result in such a consistant inconsistency.

    Any suggestions? Before I leave I would like, ore more time, to thank you and applaud you for the time and effort you have put into this one conversation alone. I have been programming in several languages for a while now with php kind of being a bit of a bastard child that i like to take to the park once in a while. In the many years that I have dabbled in programming, I have found less than 3 that were so willing to help the community. I would like to applaud you for your efforts and hope that our fellow humans may see people like you and be more willing to help a neighbor as you have.

  26. Please excuse my typo in the first code listing. It should read:

    echo time() . " - " . $row[logonDateTime] . "";
    echo "difference is " . (time() - $row['logonDateTime']) . "";
    echo time() . " - " . $row[logoffDateTime] . "";
    echo "difference is " . (time() - $row['logoffDateTime']) . "";

    The only change was the reference to the database item $row[logoffDateTime] on the third line. It had no impact on the output other than to make it a little confusing to read where the data was outputting from. The output above is still accurate as the piece of code that calculated it was correct, just not its label.

  27. Solved

    Ok perhaps you have a better solution than what I came up with. The issue came from your first test of is_int(). In my situation where I am being returned a timestamp created by mysql from a datetime filed, php was treating the timestamp as a string. I do not know why it would default to treating a “string” of numbers as a literal string as aposed to one number but i used the following hack to make it work. Do you know of a better way to typecast with a language that has no casting?


    $lastLogon = dateDiff(time(), ($row[logonDateTime] + 0));
    echo $lastLogon . "";
    $lastLogoff = dateDiff(time(), ($row[logoffDateTime] + 0));
    echo $lastLogoff . "";

    Notice that I have added 0 to the returned timestamp.

    Any suggestions?

  28. Better Solution

    $lastLogon = dateDiff(time(), (int)$row[logonDateTime]);
    echo $lastLogon . "";
    $lastLogoff = dateDiff(time(), (int)$row[logoffDateTime]);
    echo $lastLogoff . "";

    Ok so its official, i have been behind this screen for way too long. Thank you again for your contributions.

    • Hi Wes,

      You got this totally solved? Or do you need some help with this still?

  29. Thank for the function!
    I’ve read many dateDiff functions on the internet which don’t contemplate the years problem.

    Santiago

  30. Very nice post. I tried writing something myself for my site, but no luck, so I Googled. Your site was 3rd listed and I’m so happy I found it. Bookmarked and waiting for more.

    This function makes my life so easy! :) *applauds*

  31. Hi JR
    Will you help me also plzzzzzz
    My prob is i cant find the diff when the total hours exceeded above 24
    that is

    Assigned Hours is 30:00:00
    Completed hours is 20:00:00

    i want to find the difference between these hours
    that is
    Remaining Hours as 10:00:00

    will you please help me as soon as possible

    • Hi Keerthi,

      So you are using only hours, minutes and seconds without days, months and years?

  32. yes…..
    if assigned hours or completed hours gets greater than 24:00:00 ,then i’m not able to find the difference.wht will i do to find the difference.

    In one of the above codes it shows how to find out the total no of working hours.
    After that how can i find the diff between assigned and completed hours??
    Plz help me

    • Hi again Keerthi,

      I think best way is simply convert hours, minutes and seconds to seconds and then calculate difference and then convert seconds back to hours, minutes and seconds. I wrote following code to do this:

      <?php
      	function hmsDiff ($assigned_time, $completed_time) {
      		$assigned_seconds = hmsToSeconds($assigned_time);
      		$completed_seconds = hmsToSeconds($completed_time);
       
      		$remaining_seconds = $assigned_seconds - $completed_seconds;
       
      		return secondsToHMS($remaining_seconds);
      	}
       
      	function hmsToSeconds ($hms) {
      		$total_seconds = 0;
      		list($hours, $minutes, $seconds) = explode(":", $hms);
      		$total_seconds += $hours * 60 * 60;
      		$total_seconds += $minutes * 60;
      		$total_seconds += $seconds;
       
      		return $total_seconds;
      	}
       
      	function secondsToHMS ($seconds) {
      		$minutes = (int)($seconds / 60); 
      		$seconds = $seconds % 60;
      		$hours = (int)($minutes / 60); 
      		$minutes = $minutes % 60;
       
      		return  sprintf("%02d", $hours) . ":" . 
      			sprintf("%02d", $minutes) . ":" . 
       			sprintf("%02d", $seconds);
      	}
       
      ?>

      Function usage:

      <?php
      	echo hmsDiff("30:00:00", "20:00:00") . "\n";
       
      	echo hmsDiff("47:00:00", "26:45:00") . "\n";
       
      	echo hmsDiff("00:45:30", "00:30:15") . "\n";
       
      	echo hmsDiff("10:45:30", "10:45:30") . "\n";
      ?>

      Output:

      $ php time.php 
      10:00:00
      20:15:00
      00:15:15
      00:00:00

      This code is only quick example without any input value checks and I assume that the assigned time is always equal or greater than completed time. So this is maybe not production ready code, but I think you get the idea… :)

  33. Thank alot….
    it works
    thank you so much

    • You’re welcome! ;)

  34. how can i set a reminder for my insurance policies that reminds me 7 days before the due date of premium. one is yearly and another is monthly. Policies were bought in june 2001(yr) and oct 2007(monthly).


  35. $trime1 = time();
    $trime2 = "(".$get_info['dt'].")";
    $trime3 = "(".$get_info['lastchange'].")";

    if ($get_info['status'] == 3){
    $diff = "\t".dateDiff($trime2, $trime3)."\n";
    echo $diff;}

    else {
    $diff = "\t".dateDiff($trime2, $trime1)."\n";
    echo $diff;}

    Thanks for this function, been scourging around the net for it. But i was having an issue. As you can see on the code above, i’m trying to do a datediff on a row list directly from my SQL database. dt column data type is datetime while lastchange column is timestamp. Result from doing the code above is : 41 years, 10 months, 13 days, 4 hours, 2 minutes, 52 seconds. Since i’m practically not too familiar with php code, may i know whether is there a way for me to tackle this issue? Thanks!

    • Hi BlackHowling,

      Could you also post exact values (MySQL datetime and timestamp), what you get from MySQL database?

      Looks some problem with datetime data type, but if you could “echo” those values and post here…

      • Will do.

        These are 3 example values from DT column (datetime data type) based on my original SQL query made for the project that i’m currently doing (a total of 100 rows).
        A1 2011-11-14 14:57:32
        A2 2011-11-14 14:36:05
        A3 2011-11-14 14:13:21

        and these would be the lastchange which is in timestamp datatype,
        B1 2011-11-14 15:11:10
        B2 2011-11-14 15:12:10
        B3 2011-11-14 14:13:21

        Basically im trying to pull of an aging column, which your function will work as the function to calculate the aging, for example, B1 – A1, B2 – A2 and lastly B3 – A1. So it will print out the aging period of each row A1, A2, A3… etc. Seeing the format is basically the same in the data, it shouldn’t be an issue right? I’ve also tried Wes’s method, but failed. :(

        • If I try run dateDiff function with your values:

          echo "B1 - A1 diff: " . dateDiff('2011-11-14 15:11:10', '2011-11-14 14:57:32') . "\n";
          echo "B2 - A2 diff: " . dateDiff('2011-11-14 15:12:10', '2011-11-14 14:36:05') . "\n";
          echo "B3 - A3 diff: " . dateDiff('2011-11-14 14:13:21', '2011-11-14 14:13:21') . "\n";

          I get following output:

          B1 - A1 diff: 13 minutes, 38 seconds
          B2 - A2 diff: 36 minutes, 5 seconds
          B3 - A3 diff:
          

          Note the last one is empty, because there is no difference…

          So I’m not sure anymore, what is the problem? :)

  36. Thank you for your time, by the way. Really appreciated. Anyway, the issue lies at it doesn’t want to calculate my SQL queries unless i put up the values inside of it which i can’t because the data was updated every half an hour. Therefor, i was trying to make the function to auto calculate the column and print out a result on a new row for it, perpendicular to the data that was listed. Let me give you the link of a test page i made. http://support2.netmyne.com/testing.php (while it’s still there). As you can see, instead of publishing it in a new row, it decides to give up and print the Aging (the one where i used the function) down below, calculating god knows what.

    • Thanks! Now I got it, what you are doing… :)

      But if you want print that aging every rows then, I think it is not big problem…just run dateDiff function once per every row with your timestamps?

      • Thanks. Let me try a simple php method based on that logic.

        Let’s say the table “test” contains dt(dateTime), lastchange(timestamp), and status(to check for open/resolved).

        Example,
        “SELECT dt,lastchange,status FROM test ORDER BY dt DESC LIMIT 100″ would be the SQL query to get the latest data sorted by the latest data accordingly to the dt column,

        Full code would be;


        $time2) {
        $ttime = $time1;
        $time1 = $time2;
        $time2 = $ttime;
        }

        // Set up intervals and diffs arrays
        $intervals = array('year','month','day','hour','minute','second');
        $diffs = array();

        // Loop thru all intervals
        foreach ($intervals as $interval) {
        // Set default diff to 0
        $diffs[$interval] = 0;
        // Create temp time from time1 and interval
        $ttime = strtotime("+1 " . $interval, $time1);
        // Loop until temp time is smaller than time2
        while ($time2 >= $ttime) {
        $time1 = $ttime;
        $diffs[$interval]++;
        // Create new temp time from time1 and interval
        $ttime = strtotime("+1 " . $interval, $time1);
        }
        }

        $count = 0;
        $times = array();
        // Loop thru all diffs
        foreach ($diffs as $interval => $value) {
        // Break if we have needed precission
        if ($count >= $precision) {
        break;
        }
        // Add value and interval
        // if value is bigger than 0
        if ($value > 0) {
        // Add s if value is not 1
        if ($value != 1) {
        $interval .= "s";
        }
        // Add value and interval to times array
        $times[] = $value . " " . $interval;
        $count++;
        }
        }

        // Return string with times
        return implode(", ", $times);
        }

        $result = mysql_query("SELECT dt,lastchange,status FROM test ORDER BY dt DESC LIMIT 100");

        echo "

        Date Receive Rating
        Last Change
        Aging
        ";

        while($row = mysql_fetch_array($result))
        {
        echo "";
        echo "" . $row['dt'] . "";
        echo "" . $row['lastchange'] . "";

        $trime1 = time();
        $trime2 = "(".$row['dt'].")";
        $trime3 = "(".$row['lastchange'].")";

        if ($get_info['status'] == 3){
        $diff = "\t".dateDiff($trime2, $trime3)."\n";

        echo $diff;}

        else {
        $diff = "\t".dateDiff($trime2, $trime1)."\n";

        echo $diff;}

        echo "";
        }
        echo "";

        mysql_close($con);
        ?>

        http://support2.netmyne.com/testing.php still getting the same result :( /chugs a beer. i just don’t understand why it total out the aging, and print it on every single row, lol.

        • Thanks! Now I finally see where the problem is… :)

          The problem is brackets. Let’s see…following:

          $trime2 = "(".$row['dt'].")";
          $trime3 = "(".$row['lastchange'].")";

          Should be simply:

          $trime2 = $row['dt'];
          $trime3 = $row['lastchange'];

          Do you get it working now? :D

          • That’s it! OH MY GOD! SUCH SIMPLE THING ! D: Thank you very much, good sir! In the end it was my coding’s fault! I apologized! D: Thanks! /toss a beer

            New Result :
            2011-11-15 14:21:02 2011-11-15 14:23:13 2 hours, 23 seconds

            2011-11-15 13:55:30 2011-11-15 14:17:05 2 hours, 25 minutes, 55 seconds

            2011-11-15 12:13:43 2011-11-15 13:24:59 4 hours, 7 minutes, 42 seconds

            • You are welcome! Yes, very simple thing, but hard to find… :D Funniest thing is that you posted it on your first post… :)

              And no problems! :) It’s most important that you got it working as it should be! ;D

  37. hello. wonderful script.

    I am trying to find the difference between a given date, that can be from the past or from the future, and the current date. But the current script only says the difference. It does not say for example 14 days ago, or 14 days left. How can I do that? How can find a non-absolute difference in days only. The output can be in negative if the given date is from the past and positive if the given date is from the future. I am trying to find the difference in days so i dont need all the year, min, seconds, month variables. Thanks
    Abu

    • Hi Abu,

      Thanks!

      This is totally new topic and off topic, so could you please post your question to our forums -> PHP Board let’s see what we could do. It’s better place to discuss anyways. :)

      • @JR.
        ok. I did.
        Thanks.
        Abu

        • Thanks Abu! :) I will check your problem soon…

  38. Why not use the native functionality? The format function in the DateTime class can be used to output the same information with just a few lines of code.


    $now = new DateTime('now');
    $then = new DateTime($date);
    $diff = $now->diff($then);
    echo $diff->format('%a days');

    • Hi Charlie,

      Thanks, I actually post this style solution here and also native MySQL example. ;)

  39. I love you code JR it’s really functional but is there a way I can get the difference ONLY in one of the time.

    For example, i want the following:

    difference between 2011-12-14 21:54 and 2011-12-16 20:45

    — if i need it in HOURS then it will give for example 22.8 Hours
    — if i need it in MINUTES for examples it will return 1368
    and so on??

    if we were able to to this it will HELP me alot.

    THANKS AGAIN
    Sevag

    • Hi Sevag,

      What intervals you want to use? Seconds, minutes, hours, days…?

      • Years
        Month
        Week
        Day
        Hour
        Minutes

        I need this for the following reason

        If my client asked for service every 10 minutes between 2011-12-16 10:00 till 2011-12-17 10:25

        Since he picked minutes as interval then i want something that gives me in this case 1465.
        Then i will do simply 1465 / (10) = 14.65. So this means 14 services.

        Now if he were same time interval but he picked every 2 hours
        Then the formula should give me 24.2
        Then i do 24.2 / 2 = 12.1 . so this means 12 services.

        • Sorry 1465/10 = 146.5 => 146 services

          • Hi again Sevag,

            Do you need output example as 24.2 hours or is just 24 hours integer value enough? This full double/floating point value with decimals is easy to get with minute, hour, day, week intervals, but it’s very hard to get with month and year intervals, because we can’t use fixed seconds for month and year. If you want to use this date diff function logic and accuracy, then it’s only possible to get integer values.

            • just the integer value is enough

              but supposing minutes interval

              instead of getting
              1 day 3 minutes

              I get
              1443 minutes

              • Okey :) Then check following code:

                <?php
                 
                  // Set timezone
                  date_default_timezone_set("UTC");
                 
                  // Time format is UNIX timestamp or
                  // PHP strtotime compatible strings
                  function dateDiff($time1, $time2, $interval) {
                    // If not numeric then convert texts to unix timestamps
                    if (!is_int($time1)) {
                      $time1 = strtotime($time1);
                    }
                    if (!is_int($time2)) {
                      $time2 = strtotime($time2);
                    }
                 
                    // If time1 is bigger than time2
                    // Then swap time1 and time2
                    if ($time1 > $time2) {
                      $ttime = $time1;
                      $time1 = $time2;
                      $time2 = $ttime;
                    }
                 
                    // Set up intervals and diffs arrays
                    $intervals = array('year','month','day','hour','minute','second');
                    if (!in_array($interval, $intervals)) {
                      return false;
                    }
                 
                    $diff = 0;
                    // Create temp time from time1 and interval
                    $ttime = strtotime("+1 " . $interval, $time1);
                    // Loop until temp time is smaller than time2
                    while ($time2 >= $ttime) {
                      $time1 = $ttime;
                      $diff++;
                      // Create new temp time from time1 and interval
                      $ttime = strtotime("+1 " . $interval, $time1);
                    }
                 
                    return $diff;
                  }
                 
                  // Testing...
                  echo "Timestamps 2011-12-16 10:00 - 2011-12-17 10:25\n";
                  echo "Minute interval: " . dateDiff('2011-12-16 10:00', '2011-12-17 10:25', 'minute') . "\n";
                  echo "Hour interval: " . dateDiff('2011-12-16 10:00', '2011-12-17 10:25', 'hour') . "\n";
                  echo "Day interval: " . dateDiff('2011-12-16 10:00', '2011-12-17 10:25', 'day') . "\n";
                 
                  echo "\n\n";
                 
                  echo "Timestamps 2011-12-16 10:00 - 2014-06-17 10:25\n";
                  echo "Hour interval: " . dateDiff('2011-12-16 10:00', '2014-06-17 10:25', 'hour') . "\n";
                  echo "Day interval: " . dateDiff('2011-12-16 10:00', '2014-06-17 10:25', 'day') . "\n";
                  echo "Month interval: " . dateDiff('2011-12-16 10:00', '2014-06-17 10:25', 'month') . "\n";
                  echo "Year interval: " . dateDiff('2011-12-16 10:00', '2014-06-17 10:25', 'year') . "\n";
                 
                ?>

                Output:

                Timestamps 2011-12-16 10:00 - 2011-12-17 10:25
                Minute interval: 1465
                Hour interval: 24
                Day interval: 1
                
                Timestamps 2011-12-16 10:00 - 2014-06-17 10:25
                Hour interval: 21936
                Day interval: 914
                Month interval: 30
                Year interval: 2
                

                Note. first examples use your timestamps and last examples use date 2014-06-17… :)

                I just tested this quickly and seems to be working, please let me know, if you have any problems with that?

                • First of all thank you for your code, it helped me alot. But i just realized something that got me puzzled.

                  Suppose I have the following two time-stamps:

                  $start =’2011-12-18 23:19:00′;
                  $end =’2012-02-08 13:20:00′;
                  $interval=3;

                  I tried to compute the difference in hours using two different approaches and I got a small difference.

                  1.
                  $howmany=floor($difference/($interval*60*60)+1);

                  output was 413

                  2.$howmany=(dateDiff( $start , $end , ‘hour’)/$interval)+1;

                  out was 414

                  I tried the same two approaches for minutes, days, and weeks and answers were IDENTICAL. but just never figured out why in this specific case answers weren’t the same. Any suggestions?

                  Thank you,
                  Sevag

                  • Actually, I can’t see the problem here, so let’s look at this in more detail…

                    First if we compare just fixed value approach, with dateDiff:

                    $start ='2011-12-18 23:19:00';
                    $end ='2012-02-08 13:20:00';
                    $interval=3;
                     
                    echo (strtotime($end)-strtotime($start))/(60*60) . "\n";
                     
                    echo dateDiff( $start , $end , 'hour') . "\n";

                    Output:

                    1238.0166666667
                    1238
                    

                    So this looks good, exactly same, but dateDiff output without decimals, as it should be.

                    Then divide results with three (your interval):
                    1238.0166666667 / 3 = 412.672222222
                    1238 / 3 = 412.666666667

                    Then add one (I don’t know why, but if you just have to add one):
                    412.672222222 + 1 = 413.672222222
                    412.666666667 + 1 = 413.666666667

                    Then you use floor to round first value fractions down:
                    floor(413.672222222) = 413
                    413.666666667

                    So actually second value is 413.666666667 at this point, not 414…and first value fractions is rounded down and it’s 413…

  40. you are great , your code and function is very useful

    Thanks to help all

  41. Very nice function. This is useful when the PHP version < 5.3. Since version 5.3, PHP supports method Datetime::diff( $datetime1, $datetime2 ); that might be an easier solution.

    • Hi Rilwis nice to see you here,

      Yes, this is old post and PHP’s own Datetime:diff is useful on PHP 5.3, but you still need to format output manually. And of course here is many custom modifications from original version… ;)

  42. hi all,

    I have a question to all,
    How to calculate minutes “Operational Hours” within a period.

    case example :
    Date range : 2011-11-01 to 2011-11-30,
    Non Operational Hours : between 22:00 to 08:00 week day (Mon to Frid)
    Non Operational Days : Sat + Sun

    Quest :
    How to Calculate Total “Minutes” Operational Time ??

    Please help,
    thanks for your advice …

    BP

    • Hi abang,

      Is those Operational days always from Mon to Fri?
      And is those hours fixed 08:00 – 22:00?

  43. Heej JR, your script has helped me loads. Thanks thus far! I have a quick question, a problem I can’t simply solve by myself.

    If I do:
    echo dateDiff(1267074000, time(), 3);
    it works fine.

    But if I do:
    echo dateDiff($setTime, $currentTime, 3);
    it doesn’t work, even though holding the same results.
    Is there anything I’m doing wrong?

    Cheers and much thanks in advance.

  44. Forgot to add: it gives me 42 years, xx days, etc. I can’t figure out why.

    • Hi Ben,

      Could you echo your variables $setTime and $currentTime, just before deteDiff function and post output here, like:

      echo $setTime;
      echo $currentTime;
      echo dateDiff($setTime, $currentTime, 3);
  45. Just pinched this for something too. Thanks a lot mate, works very well!

  46. Beginning of the function is hidden because of remarks in code :)

    • oops, now looks good, looks like something loading slowly

  47. I hate to bring up a really old post but this has been extremely helpful with my current project. I am doing a project that calculates tenure. An employee can work full-time, or a percentage of time. For example if the employee worked between 01/01/01 and 01/01/02 at full-time I need it to have the result as 1 year but if the employee only worked, say 20 of 40 hours a week (50%), then I should get a result of 6 months. I feel that I should be able to modify the given code to include this but I am still learning PHP and I am having more trouble than I care to admit. Is there any way you or someone else could help me?

    Thank you again.

    • Hi Jordan,

      Do you want to get finally exact weeks, days, hours, minutes? And do you have always full months and years?

  48. What I really need is just years months and days. between the two dates and then a total amount of days.

    Do i always have full months and years? Yes the dates will always be with full months and years.

    • Hi Jordan,

      It’s actually very easy to get just total amount of days between two timestamps with this function just change following line:

      $intervals = array('year','month','day','hour','minute','second');

      To:

      $intervals = array('day');

      And if you want years, months and days then change it to:

      $intervals = array('year','month','day');

      You can use this array as a parameter or use simple if…else structure to get it changed using parameter if you want use same function for both.

  49. Hi JR..!

    Thank’s for sharing this great script of yours, its very helpful!
    You just saved me from being stuck for days..
    Keep up the good work!

    Thank you so much..!^__^

    planetjane414

  50. Very helpful, nice post Cheers :)

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks/Pingbacks