Reputation: 12674
I'm using the following code to calculate the average time between a start time and an end time for a number of events (from a database):
function getATBData($siteID, $fromDate, $toDate)
{
global $pdo;
$ATBarray = array();
$maxATB;
$minATB;
$avgATB;
$totalATB=new DateTime("@0");
$totalEvents=0;
$timetable;
$query = "SELECT id, siteID, start_time, end_time FROM atb_log WHERE siteID=:siteID AND (start_time BETWEEN :fromDate AND :toDate) AND (end_time BETWEEN :fromDate AND :toDate)";
$stmt = $pdo->prepare($query);
$stmt->bindParam(":siteID", $siteID);
$stmt->bindParam(":fromDate", $fromDate);
$stmt->bindParam(":toDate", $toDate);
$stmt->execute();
foreach ($stmt as $row)
{
$timeDiff = date_diff(new DateTime($row['start_time']),new DateTime($row['end_time']), true); //force absolute
if(!isset($maxATB) OR dateIntervalInSeconds($timeDiff) > dateIntervalInSeconds($maxATB))
$maxATB = $timeDiff;
if(!isset($minATB) OR dateIntervalInSeconds($timeDiff) < dateIntervalInSeconds($minATB))
$minATB = $timeDiff;
$totalATB->add($timeDiff);
$totalEvents++;
}
if($totalEvents!=0)
{
//$avgATB=round($totalATB->getTimestamp() / $totalEvents);
$avgATB = average_time($totalATB->format("H:i:s"),$totalEvents,0);
}
else
{
$avgATB=0;
$maxATB=new DateInterval('PT0S');
$minATB=new DateInterval('PT0S');
}
$avgSeconds = new DateInterval("PT" . $avgATB . "S");
$ATBarray['max'] = $maxATB->format("%H:%I:%S");
$ATBarray['min'] = $minATB->format("%H:%I:%S");
$ATBarray['avg'] = gmdate("H:i:s",$avgATB); //$avgSeconds->format("%H:%i:%s");
$ATBarray['total'] = $totalATB->format("H:i:s");
$ATBarray['events'] = $totalEvents;
return $ATBarray;
}
Unfortunately, I'm getting extremely high averages. As an example, I'm finding that the max time is 3 seconds, the min time is 0 seconds, but the average time is 1 hour and 1 second. This is obviously impossible, so is there something wrong with how I'm calculating total and/or average? The total is rather high too, but I haven't been able to manually add up this data so I'm not sure if that is also incorrect.
Upvotes: 0
Views: 479
Reputation: 12674
EDIT:
I've changed the way I'm calculating averages. I've added the new function all above, and here is the averaging function (found here):
function average_time($total, $count, $rounding = 0) //from SO
{
$total = explode(":", strval($total));
if (count($total) !== 3) return false;
$sum = $total[0]*60*60 + $total[1]*60 + $total[2];
$average = $sum/(float)$count;
$hours = floor($average/3600);
$minutes = floor(fmod($average,3600)/60);
$seconds = number_format(fmod(fmod($average,3600),60),(int)$rounding);
if($hours<10) $hours = "0"+$hours; //add leading 0
if($minutes<10) $minutes = "0"+$minutes;
if($seconds<10) $seconds = "0"+$seconds;
return $hours.":".$minutes.":".$seconds;
}
So now my average numbers have changed and I'm trying to check the totals to see if they're correct. But I've posted that as another question, located here.
Upvotes: 0
Reputation: 913
This is most probably a DST problem. Is your code running in a U.S. timezone? Rerember that when you're using new DateTime("@0")
, this represents 1970-01-01 00:00:00 (non-DST); in the U.S., DST has started now, so the absolute value of your DateTime objects created from the database are one hour off.
Upvotes: 1