Jump to content

[SOLVED] Average time using 00:15:01 type of time


coolbeansdude51

Recommended Posts

Hello forum,

 

I am trying to figure out how to do the average time in an array full of time which is formatted like below:

20:49:44

19:50:36

03:14:15

21:45:40

21:34:11

04:07:53

etc.

 

How can I figure out the average time of all of those times? 

 

I was thinking we would have to break apart each section of the time.  So break apart the hours.  Average that.  Break apart the minutes. Average that. Break apart the seconds. Average that.

 

I am assuming the explode function would do the best for this.  Take the ':' out of the string.

 

Will that give me an accurate average?

<?
$time1 = explode(':', $string);

$hour = average($time1[0]);
$minute = average($time1[1]);
$second = average($time1[2]);

//array average( array input )
function average($input) {
return array_sum($input) / count($input);
}
?>

 

I thought that would work ... but it didn't.  It gave me an error of

"Warning: array_sum() [function.array-sum]: The argument should be an array in filelocation"

 

Any ideas?  Thanks in advance!

Link to comment
Share on other sites

Ok now ... I am thinking it should be more like this.

$i = 0;
while ($i <= 99) {
$test = explode(' ',$friends->status[$i]->created_at);
$test1 = explode(':', $test[3]);
$i++;
};

$hour = average($test1[0]);
$minute = average($test1[1]);
$second = average($test1[2]);

echo $minute;

//array average( array input )
function average($input) {
return array_sum($input) / count($input);
}

 

But that doesn't work either.  Keeps telling me that the test1 var is not an array ... I am making it an array in the while statement?

 

Anyone got any idea's?

Link to comment
Share on other sites

Ok.  After a ton of trial and error I figure this out ...

 

<?
$i = 0;
$stop = count($friends->status->created_at);

while ($i <= $stop) {
$test = explode(' ',$friends->status[$i]->created_at);
$bigtime[$i] = $test[3];
$smaller[$i] = explode(':', $bigtime[$i]);
$hour[$i] = $smaller[$i][0];
$minute[$i] = $smaller[$i][1];
$second[$i] = $smaller[$i][2];
$i++;
};

$aveghour = round(average($hour));
$avegminute = round(average($minute));
$avegsecond = round(average($second));

//array average( array input )
function average($input) {
return array_sum($input) / count($input);
}

echo $aveghour.":".$avegminute.":".$avegsecond;
?>

 

Works for me! Hope it helps someone else.  Still wondering if it gives you an accurate average for time.  Any thoughts?

Link to comment
Share on other sites

I'm not sure how your 'array' is constructed, but when I tested your code it created an empty element at the end of each record - skewing the results (because of the <= in the while loop). Even after I corrected for that, the code still calculates incorrectly. Using the times 1:10:00 & 1:05:00 & 2:55:00 it calculated the average as 1:23:0. But, if you convert the times to minutes you get: (70 + 65 + 175) = 310 / 3 = 103 minutes averaged. 103 minutes is 1:43:00.

 

Give me a sec and I'll give you some code that works

Link to comment
Share on other sites

<?php

function averageTime($timesArr)
{
    foreach($timesArr as $timeStr)
    {
        //Convert to seconds and add to array
        $seconds[] = hms2sec($timeStr);
    }
    return sec2hms(round(array_average($seconds)));
}

function hms2sec($time)
{
    //Split time into parts
    $timeParts = explode(':', $time);
    return ($timeParts[0]*3600 + $timeParts[1]*60 + $timeParts[2]);
}

function sec2hms($seconds)
{
    $hours   = number_format(intval($seconds/3600), 0);
    $minutes = str_pad(intval($seconds%3600/60),2, '0', STR_PAD_LEFT);
    $seconds = str_pad($seconds%60,2, '0', STR_PAD_LEFT);
    return "$hours:$minutes:$seconds";
}

function array_average($array)
{
return (array_sum($array)/count($array));
}

$times = array('1:10:00', '1:05:00', '2:55:00');
echo averageTime($times);

?>

Will output 1:43:20 (which is correct).

Link to comment
Share on other sites

Looks good.  When I pump in my numbers (about 800 - 10,000) of them. I get this: 339:18:25 I then tired a different string (800 - 10,000) of them and got 342:48:1720. This is 24hour time UTC. I am guessing the hour's section is off and maybe even the seconds section.

 

Any suggestions?

Link to comment
Share on other sites

Also. I had to include the while statement to make it work. $friends->status[$i]->created_at section is a massive array of XML data.  The created at part is all I want. To separate it out I use the explode method.  Because the array looks like this:

[98] => Array

        (

            [0] => Fri

            [1] => Mar

            [2] => 06

            [3] => 18:28:22

            [4] => +0000

            [5] => 2009

        )

 

That is why the function must process only the 3 section of the array cause that is the part that has all the times in it. Any other help or advise?

 

$i = 0;
$stop = count($friends->status);
while ($i <= $stop) {
	$times[] = explode(' ',$friends->status[$i]->created_at);
	$i++;
};

function averageTime($timesArr)
{
    foreach($timesArr as $timeStr)
    {
        //Convert to seconds and add to array
        $seconds[] = hms2sec($timeStr);
    }
    return sec2hms(round(array_average($seconds)));
}

function hms2sec($time)
{
    //Split time into parts
    $timeParts = explode(':', $time);
    return ($timeParts[0]*3600 + $timeParts[1]*60 + $timeParts[2]);
}

function sec2hms($seconds)
{
    $hours   = number_format(intval($seconds/3600), 0);
    $minutes = str_pad(intval($seconds%3600/60),2, '0', STR_PAD_LEFT);
    $seconds = str_pad($seconds%60,2, '0', STR_PAD_LEFT);
    return "$hours:$minutes:$seconds";
}

function array_average($array)
{
   return (array_sum($array)/count($array));
}

echo averageTime($times[3]);

Link to comment
Share on other sites

Hmm.. Those are some odd results. But, looking at the code you posted I'm seeing some errors and odd logic.

 

First off, there is the error I alluded to earlier

$i = 0;
$stop = count($friends->status);
while ($i <= $stop) {

If there are 10 records and the first record is at index 0, then our loop should continue until index number 9 (0-9 is 10 elements). So the while loop should be "($i < $stop)" not "($i <= $stop)" which will go from 0 to 10, i.e. 11 elements.

 

Next you have this code

$times[] = explode(' ',$friends->status[$i]->created_at);

 

You state that $friends->status[$i]->created_at is an array, but you use explode on it? Even if we assume it is a string that you then convert to an array, you are then assigning that array to $times[], but then you only process $times[3]. I *think* what you want to be processing is $times[n][3], where n represents each record.

 

Give this a try

<?php
$i = 0;
$record_count = count($friends->status)
while ($i < $record_count)
{
    $record = explode(' ', $friends->status[$i]->created_at);
    $thisTime = $record[3];
    if (!echo preg_match('/^\d{1,2}:\d{1,2}:\d{1,2}$/', $thisTime)
    {
        echo "Invalid time: [$thisTime], record $i<br>";
    }
    else
    {
        $times[] = $thisTime;
    }
    $i++;
}

function averageTime($timesArr)
{
    foreach($timesArr as $timeStr)
    {
        //Convert to seconds and add to array
        $seconds[] = hms2sec($timeStr);
    }
    return sec2hms(round(array_average($seconds)));
}

function hms2sec($time)
{
    //Split time into parts
    $timeParts = explode(':', $time);
    $seconds = ($timeParts[0]*3600 + $timeParts[1]*60 + $timeParts[2]);
//echo "hms2sec: Input ($time), Output ($seconds}<br>";
    return $seconds;
}

function sec2hms($seconds)
{
    $hours   = intval($seconds/3600);
    $minutes = intval($seconds%3600/60);
    $seconds = ($seconds%60);
    $hms = sprintf("%s:%02s:%02s", $hours, $minutes, $seconds);
echo "sec2hms: Input ($seconds), Output ($hms}<br>";
    return $hms;
}

function array_average($array)
{
   return (array_sum($array)/count($array));
}

echo averageTime($times);

?>

 

For further debugging, hard code the value of $record_count to be something like 10 and then uncomment the other debuggin line in the hms2sec() function. I wouldn't have that line uncommented if you are running thousands of records.

 

Link to comment
Share on other sites

Looks like that worked! You missed a couple of ('s and ;'s so I edited the code! This is what it should look like. Also I am assuming that the "if(!echo preg_match" was an error and should be "if(!preg_match".  Am I correct in that?

 

$i = 0;
$record_count = count($friends->status);
while($i < $record_count) {
    $record = explode(' ', $friends->status[$i]->created_at);
    $thisTime = $record[3];
    	if(!preg_match('/^\d{1,2}:\d{1,2}:\d{1,2}$/', $thisTime)){
       		echo "Invalid time: [$thisTime], record $i<br>";
	} else {
       		$times[] = $thisTime;
    	}
    $i++;
}

function averageTime($timesArr)
{
    foreach($timesArr as $timeStr)
    {
        //Convert to seconds and add to array
        $seconds[] = hms2sec($timeStr);
    }
    return sec2hms(round(array_average($seconds)));
}

function hms2sec($time)
{
    //Split time into parts
    $timeParts = explode(':', $time);
    $seconds = ($timeParts[0]*3600 + $timeParts[1]*60 + $timeParts[2]);
//echo "hms2sec: Input ($time), Output ($seconds}<br>";
    return $seconds;
}

function sec2hms($seconds)
{
    $hours   = intval($seconds/3600);
    $minutes = intval($seconds%3600/60);
    $seconds = ($seconds%60);
    $hms = sprintf("%s:%02s:%02s", $hours, $minutes, $seconds);
echo "sec2hms: Input ($seconds), Output ($hms}<br>";
    return $hms;
}

function array_average($array)
{
   return (array_sum($array)/count($array));
}

echo averageTime($times);

 

Thanks so much for your help!

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.