Page 1 of 1

Requesting help with date/time/age calculation function

Posted: Thu Mar 23, 2006 8:16 pm
by rbsterli
feyd | Please use

Code: Select all

and

Code: Select all

tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]


Hi Folks!

PHP Newbie here and I got this little code snippet somewhere on the Internet recently.  It seems to work well for the most part but the "day" calculation seems to be off.  I've only been analyzing it for about 36 hours but I'm thinking it may be a timezone issue or something.  I'm using it on a page I created for a newborn so I wish to calculate his exact age in "days, minutes and seconds"

Minutes and seconds obviously aren't "required", but is a real neat novelty!  Anywho.. I am running this on my own Windows server which the Time and TZ are set correctly.  When I run phpinfo, it also shows correct time, but this snippet seems to jump to an additional day after 7:00PM EST.  Maybe it's off all the time, I can only confirm that tomorrow.  But.. Here's the code, I found it in a blog from 2002 and there is no way to contact the author.  Please help if anyone can.  Thanks in advance.

(I am trying to calculate age from a time of birth of 3/21/2006 10:21AM EST - [url=http://www.richsterling.com/forum/drew.php]EXAMPLE[/url])

Code: Select all

<?php
function date_delta($ts_start_date, $ts_end_date) {
  $secs_in_day = 86400;

  $i_years = gmdate('Y', $ts_end_date) - gmdate('Y', $ts_start_date);
  $i_months = gmdate('m', $ts_end_date) - gmdate('m', $ts_start_date);
  $i_days = gmdate('d', $ts_end_date) - gmdate('d', $ts_start_date);
  if ($i_days < 0)
    $i_months--;
  if ($i_months < 0) {
    $i_years--;
    $i_months += 12;
  }
  if ($i_days < 0) {
    $i_days = gmdate('d', gmmktime(0, 0, 0,
      gmdate('m', $ts_start_date)+1,
      0,
      gmdate('Y', $ts_start_date))) -
      gmdate('d', $ts_start_date);
    $i_days += gmdate('d', $ts_end_date);
  }

  # calculate HMS delta
  $f_delta = $ts_end_date - $ts_start_date;
  $f_secs = $f_delta % $secs_in_day;
  $f_secs -= ($i_secs = $f_secs % 60);
  $i_mins = intval($f_secs/60)%60;
  $f_secs -= $i_mins * 60;
  $i_hours = intval($f_secs/3600);

  return array($i_years, $i_months, $i_days,
               $i_hours, $i_mins, $i_secs);
}

function calculate_age($s_start_date,
    $s_end_date = '',
    $b_show_days = 0) {
  $b_show_time = strlen($s_start_date > ;
  $ts_start_date =
    mktime(substr($s_start_date, 8, 2),
      substr($s_start_date, 10, 2),
      substr($s_start_date, 12, 2),
      substr($s_start_date, 4, 2),
      substr($s_start_date, 6, 2),
      substr($s_start_date, 0, 4));
  if ($s_end_date) {
    $ts_end_date =
      mktime(substr($s_end_date, 8, 2),
        substr($s_end_date, 10, 2),
        substr($s_end_date, 12, 2),
        substr($s_end_date, 4, 2),
        substr($s_end_date, 6, 2),
        substr($s_end_date, 0, 4));
  } else {
    $ts_end_date = time();
  }

  list ($i_age_years, $i_age_months, $i_age_days,
        $i_age_hours, $i_age_mins, $i_age_secs) =
       date_delta($ts_start_date, $ts_end_date);

  # output
  $s_age = '';
  if ($i_age_years)
    $s_age .= "$i_age_years year".
      (abs($i_age_years)>1?'s':'');
  if ($i_age_months)
    $s_age .= ($s_age?', ':'').
      "$i_age_months month".
      (abs($i_age_months)>1?'s':'');
  if ($b_show_days && $i_age_days)
    $s_age .= ($s_age?', ':'').
      "$i_age_days day".
      (abs($i_age_days)>1?'s':'');

  if ($b_show_time && $i_age_hours)
    $s_age .= ($s_age?', ':'').
      "$i_age_hours hour".
      (abs($i_age_hours)>1?'s':'');
  if ($b_show_time && $i_age_mins)
    $s_age .= ($s_age?', ':'').
      "$i_age_mins minute".
      (abs($i_age_mins)>1?'s':'');
  if ($b_show_time && $i_age_secs)
    $s_age .= ($s_age?', ':'').
      "$i_age_secs second".
      (abs($i_age_secs)>1?'s':'');
  return $s_age;
}


?> 
<?= calculate_age('20060316102100','','1') ?>
Thanks again,
rbsterli
RichSterling.com - PC Support, Woodworking Links and BBQ Forums
Image


feyd | Please use

Code: Select all

and

Code: Select all

tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]

Posted: Thu Mar 23, 2006 8:20 pm
by Benjamin
This code is using gmdate which I would assume is using greenwhich meantime regardless of your timezone setting. You will need to subtract your timezone offset from it in order to get the correct results.

Posted: Thu Mar 23, 2006 8:31 pm
by rbsterli
feyd | Please use

Code: Select all

and

Code: Select all

tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]


Thanks.. I tried that.  It does adjust the hours, but it makes the hours 5 hours off.  It doesn't affect the day count.  The hours, minutes and seconds are always accurate - the number of days just reflect "an extra day" after 7PM.

-Weird.  I had a sigh of a days worth of research - relief, for a second.  Made the change and it didn't do it, although sounding very logical      Thanks though..

My guess is that I need to make up the 5 hour difference somewhere in this section where the days are calculated??   If this is correct, can anyone help tell me where???

Code: Select all

$i_days = gmdate('d', $ts_end_date) - gmdate('d', $ts_start_date); 
  if ($i_days < 0) 
    $i_months--; 
  if ($i_months < 0) { 
    $i_years--; 
    $i_months += 12; 
  } 
  if ($i_days < 0) { 
    $i_days = gmdate('d', gmmktime(0, 0, 0, 
      gmdate('m', $ts_start_date)+1, 
      0, 
      gmdate('Y', $ts_start_date))) - 
      gmdate('d', $ts_start_date); 
    $i_days += gmdate('d', $ts_end_date); 
  }

feyd | Please use

Code: Select all

and

Code: Select all

tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read:  [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]

Posted: Thu Mar 23, 2006 8:39 pm
by Benjamin

Code: Select all

function GetAge($DOB) {
  list($Year, $Month, $Day) = explode("-",$DOB);
  $YearDifference  = date("Y") - $Year;
  $MonthDifference = date("m") - $Month;
  $DayDifference   = date("d") - $day;
  if ($DayDifference < 0 || $MonthDifference < 0) {
    $YearDifference--;
  }
  return $YearDifference;
}
Here is a function I wrote which returns the age of someone in years based on a dob in the format 1980-01-28

It could be modified to return the age in Years, Months, days, Hours, Minutes and Seconds.