PHP: Calculate Real Differences Between Two Dates or Timestamps - Comment Page: 2

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...

226 comments on “PHP: Calculate Real Differences Between Two Dates or Timestamps - Comment Page: 2

1 2 3 4 10
    1. @Andy

      Nice to hear that you get problem solved, but thats why my first question was Did you set right timezone when you use this function? And you answered that, you are using following date_default_timezone_set(“GMT”);. So I thought that you understand the purpose of this function at the beginning of scripts.

      Following is quoted from date_default_timezone_set PHP manual:
      Note: Since PHP 5.1.0 (when the date/time functions were rewritten), every call to a date/time function will generate a E_NOTICE if the timezone isn’t valid, and/or a E_WARNING message if using the system settings or the TZ environment variable.

      So date_default_timezone_set call is there because I just want to ensure that the function works without E_NOTICE and E_WARNING messages for all . Of course, I assume that every user to change the time zone correct or remove it completely if it is not needed.

      Btw. It is important to first examine the code in more detail before you copy it in any proper use. All codes are similar examples, and of course it is very important to understand that what the code actually does. And modify the codes to suit own projects, if it does not correspond fully to what is needed.

      Reply
    2. it works……………
      thanks ……………………………..

      Reply
    3. $start_working_hours = 08:00:00
      $launc_time = 30 minutes
      $end_working_hours = 16:00:00
      $start_time_product_A = 27 July 2010 08:00:00
      $end_time_product_A = 28 July 2010 10:00:00

      I don’t really want the years, months, days, hours showing. How to calculate time product A = 570 minutes? thx.

      Reply
      • Hi evang,

        Your question is not very clear. There is nothing to indicate that when this “launc_time” (maybe lunch_time) is?

        If I understand correctly, that what you want to calculate, then one simple possible solution is count all full days and calculate (7.5 x 60) minutes/per full day and then handle first and last day minutes in some way, that you want.

        Your example logic goes like following:
        If first day start time <= 08:00:00 then it's full day If last day end time >= 16:00:00 then it’s full day
        Else first day and last day need some other handling

        27 July is full day 7.5 x 60 minutes = 450 minutes
        28 July is not full day 2 x 60 minutes = 120 minutes
        total is 570 minutes

        So this is just logic for helping to write real code.

        Reply
    4. Hey JR, been a while… had to do a bit of yahooing to find this page again. In any case, if you check out my site you will see how I’m using your code ;-)

      Anyway, as to why I’m here today… I was wondering if you could help me with something I’d like to achieve with your code. I think it might be a rather nice addition, for me anyway. I can pay your about $5 – $10 for this hack if you’d like…

      So here’s the deal…

      Actually, I want to side track just for a sec…

      When the days reach triple digits it might look like 0000, well where would I use number_format() to get it to add the commas in the appropriate places when the days go triple etc. ? I looked but it’s possible I’m just missing it after al this work I’ve been doing heh.

      Ok, now here’s the deal heh..

      Every time a new year passes instead of showing something like ??? Days, ?? Hours, ??Minutes I would like it to show something like this…

      Happy (1st, 2nd, 3rd, 4th etc.) Birthday myu2sig.com !

      I know this can be achieved but have no idea what to do to do it and I would really love your help with this modification JR. The only problem I can see maybe causing any issues would be with telling it when exactly a year has passed because of leap years etc. Off the top of my head though I can see that as being the only obstacle.

      Reply
    5. I thought I would add that the “message” that should show every time a year passes should be shown all day and that when this day is over it would start showing the time again (??? Days, ?? Hours, ?? Minutes).

      So since I deleted the default timezone line it’s going by my server time to determine my TZ which is EST / EDT it should know that a day begins at 12am and ends at 11:59pm that night.

      So lets say today was my sites 1st birthday, at 12am this morning it should have started showing Happy 1st Birthday myu2sig.com ! instead of normal time stuff and it would show this all day. Now come 11:59pm that same day / 12am the next day it would start showing the normal time stuff again and every time a new year passes the message updates accordingly.

      Happy (1st, 2nd, 3rd, 4th etc.) Birthday myu2sig.com !

      Reply
    6. Here’s my existing code incase you need it…

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

      // Set up intervals and diffs arrays
      $intervals = array('Day', 'Hour', 'Minute');
      $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 .= "s";
      }
      // Add value and interval to times array
      $times[] = $value . " " . $interval;
      $count++;
      }
      }

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

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

      ?>

      Reply
    7. Hi again Andy,

      It does not make sense to use this function for such simple calculation. You don’t need to know that how long time has passed, but you have to know the original birthday and current date.

      So you need to extract dates, months and years from birthday date and current date. Then make simple comparison with months and dates. If they are the same, then simply calculate current year minus year birthday year and that’s all.

      I wrote a quick simple PHP code to make this work:

      
      
      

      Note: this needs of course styling, but this is logic to show birthday… :)

      Reply
    8. Thx for the reply, I’m not gonna lie… I know little to nothing about PHP. I know some minore things to help get me by with small fixes to my site which is PHP crazy but I had to hire a coder to build it for me. As for my idea My site rolls over 1 day at midnight so like right now my counter says 173 Days, 11 Hours, 16 Minutes but come midnight tonight / tomorrow morning it would read 174 days. Now sorry to sound like a broken record, just habbit but, lets say tomorrow was my sites 1yr birthday. Then staring tonight at moidnight / tomorrow morning it should read something like Happy 1st B-Day myu2sig.com ! and stay that way all day and then revert back to showing time the next day. Then come the sites 2nd birthday it would show Happy 2nd B-Day myu2sig.com ! so on and so forth for every 1yr therafter. If I come close to understanding what you wrote all it will do is show the number have years passed since the birthday and then show nothing if it’s not a birthday. http://www.myu2sig.com/birthday.php – Like today it shows 3 given the default dates but come tomorrow it should show nothing (a blank page).

      Reply
    9. Ok, so I made a goot bit of headway with this, all be it not much… Anyway, everything is exactly how I want it except for the english ordinal suffix. I don’t know what to do to get it to add the st, nd, rd and th for the appropriate years.

      Ex. 1st, 2nd, 3rd, 4th etc. etc. etc.

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

      // Set up intervals and diffs arrays
      $intervals = array('Day', 'Hour', 'Minute');
      $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 .= "s";
      }
      // Add value and interval to times array
      $times[] = $value . " " . $interval;
      $count++;
      }
      }

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

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

      ?>

      Reply
    10. Hi Andy,

      Here is simple PHP function to add ordinal suffix. I tested this quickly, but looks like, it is working…

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

      In your case, use this as follows:
      1. Add function to inside tags.
      2. And do following change to your code:

      
      // Original
      echo 'Happy ', $current_year - $birthday_year, ' B-Day myu2sig.com !';
      
      // Changed to
      echo 'Happy ', addOrdinalSuffix($current_year - $birthday_year), ' B-Day myu2sig.com !';
      

      I hope this helped you to achieve what you wanted? :)

      Reply
    11. Oh it did help heh, one thing though… like I was asking before… I made my time code 0 to use as an example but see: http://www.myu2sig.com/birthday.php

      As of this posting the days read 14839 Days where would number_format() be used to get it tto read 14,839 Days ?

      Reply
    12. You must love me lol, anyway, I wanted to try and change Hour / Hours to Hr / Hrs and Minute / Minutes to Min / Mins but when I do it breaks the script. What needs to be done to get that working ?

      I only just now thought of this because I’m trying to think of a way to save a few pxs in width… Thx JR ;-)

      Reply
    13. Hi Andy,

      It is okey that you’re not a pro programmer and you want to use this example to help you, so therefore of course I will help you gladly :)

      First number_format function usage is simple, like following:

      
      echo number_format(14839, 0, '', ',');
      
      // Real usage
      number_format($value, 0, '', ',');
      

      Reason why changing Hour to Hr and Minute to Min break the script is strtotime function, which does not understand this shorter format. Simple solution to this is to give each value their own display name, which can be changed easily.

      Add following line

      
      $interval_names = array('Day' => 'Day', 'Hour' => 'Hr', 'Minute' => 'Min');
      

      after $intervals = array(‘Day’, ‘Hour’, ‘Minute’); line.

      Then replace $times[] = $value . ” ” . $interval; line with following:strong

      
      $times[] = $value . " " . $interval_names[$interval];
      

      And you are done.

      I do not tested this very well, so if this doesn’t work, please let me know.

      Reply
    14. I decided to do away with the number format idea because I wanted to add Years back in so people wouldnt have to do the math to figure out a more exact age. Anyway, if you look at: http://www.myu2sig.com/birthday.php

      You will see the “names” aren’t showing up, I modified your code accordingly to work with years but even before that the names wouldnt show. Here’s my code with your changes regarding shortened intercal names.

      $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 .= "s";
      }
      // Add value and interval to times array
      $times[] = $value . " " . $interval_names[$interval];
      $count++;
      }
      }

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

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

      ?>

      Reply
    15. Yes there was little mistake…try following:

      
        // 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++;
      
      Reply
1 2 3 4 10

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close