2

I'm looking for a way to calculate the average total duration (in DateInterval form) of an event. I have the durations in DateInterval objects, but I need to sum those up and calculate their average. Solutions I've seen so far have me adding up the different amounts by converting them to seconds, but I need to present the final form in a DateTime form.

How can I present the average duration as a DateTime value?

EDIT:

Setting the duration as follows (where $busyTime and $freeTime are DateTime objects):

$timetable[$siteID]->duration = $timetable[$siteID]->freeTime->diff($timetable[$siteID]->busyTime,true); //compare time, force to absolute (true)

Then I'm trying to sum up the durations, like so:

$totalDuration += $timetable[$siteID]->duration;

For this one, I get 129 for both the total duration AND the number of items I'm counting, which implies to me that they are all a value of 1. This is fine if so (maybe 1 second each?) but I'd like to be able to handle more than just seconds. I'm not sure if that's what is happening here.

I also tried the following, though I didn't expect it to work:

$totalDuration += $timetable[$siteID]->duration->format("Y-m-d H:i:s");

For the last one, I get 0.

muttley91
  • 12,278
  • 33
  • 106
  • 160
  • You don't. The average length of a set of intervals is no longer a date or a time [aka, a *point* in time], it is a number of seconds. [aka, a *length* of time] You need to do the math to format it into what I assume is a number of days, hours, minutes, and seconds. – Sammitch Dec 17 '13 at 22:06
  • So convert it into seconds first; do the average; then convert it back. – Ja͢ck Dec 17 '13 at 22:09
  • *Somewhat* scratch my previous statement, DateInterval *does* have a [`format()`](http://www.php.net/manual/en/dateinterval.format.php) function, but it functions entirely differently than `DateTime::format()` does because it operates on a *length* of time rather than a point. – Sammitch Dec 17 '13 at 22:11
  • Yeah I've found that, I'm just curious on how to do calculations with the duration value itself. Is it in seconds by default, and I can do the calculation with that, and then use format to display it a different way? Time to do some reading of the docs. – muttley91 Dec 17 '13 at 22:14

1 Answers1

3

You could simple create DateTime object with timestamp = 0; then ->add() all your Dateinterval's to that object; fetch ->getTimestamp() and divide it by number intervals added. You will get average number of seconds; example:

function calculateIntervalAverage() {
    $offset = new DateTime('@0');
    foreach (func_get_args() as $interval) {
        $offset->add($interval);
    }
    return round($offset->getTimestamp() / func_num_args());
}

demo

If you wish to convert seconds to DateInterval object, you can just create it with PTxS parameter:

$interval = new DateInterval("PT3600S");

demo

But this will not calculate carry-over-points, like you see on demo. If this is a problem, you can still recalculate carry-over-points; example:

class DateIntervalEnhanced extends DateInterval {

    public function recalculate()
    {
        $from = new DateTime('@0');
        $to = clone $from;
        $to->add($this);
        $diff = $from->diff($to);
        foreach ($diff as $k => $v) $this->$k = $v;
        return $this;
    }

}

demo

Glavić
  • 42,781
  • 13
  • 77
  • 107