Задачка на подсчет времени

computerworks

Новичок
Есть ряд записей, в которых фигурирует время. Начало интервала и конец интервала.
Сразу для примера три записи:
10 00 - 13 30, 12 00 - 14 00, 15 00 - 17 00.
Грубо говоря, можно сравнить с подсчетом рабочего времени сотрудника, минус перерывы и минус наложения интервалов, когда сотрудник занимался сразу несколькими делами одновременно...
Требуется решение, как подсчитать суммарное время с вычетом дыр в интервалах и вычетом наложения интервалов друг на друга. В общем виде, чтобы работало с любым количеством записей и любыми временами в. В идеале в MYSQl, но пойдет и просто сам алгоритм
В рассматриваемом выше случае получается 6 часов (с вычетом часа 14 00 - 15 00).
 

Redjik

Джедай-мастер
Сколько платишь?
или
Покажи что уже сделал чтоли.
 

Beavis

Banned
сначала объединяешь пересекающиеся периоды в один, потом считаешь суммарное кол-во времени
в чем проблема то?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Я сегодня очень добрый почему-то. Вряд ли это продлится долго...

PHP:
<?php
class Timelapse {
    protected $starts       = array();
    protected $finishs      = array();

    public function addInterval($start, $finish)
    {
        $start  = strtotime($start);
        $finish = strtotime($finish);
        $this->starts[] = $start;
        $this->finishs[] = $finish;

        return $this;
    }

    public function calculate()
    {
        $count      = count($this->starts);
        $seconds    = 0;

        sort($this->starts);
        sort($this->finishs);

        for ($i = 0; $i < $count; $i++)
        {
            if (isset($this->starts[$i+1]) && ($this->finishs[$i] > $this->starts[$i+1]))
            {
                $this->finishs[$i] = $this->starts[$i+1];
            }
            $seconds +=  ($this->finishs[$i]  -  $this->starts[$i]);
        }
        $h = (int)($seconds / 3600);
        $m = (int)(($seconds - $h*3600) / 60);
        $s = (int)($seconds - $h*3600 - $m*60);
        
        // i'm bit lazy, so let's make some black magic here ;)
        return (($h)?(($h<10)?("0".$h):$h):"00").":".(($m)?(($m<10)?("0".$m):$m):"00").":".(($s)?(($s<10)?("0".$s):$s):"00");
    }
}

$t = new Timelapse();
echo $t->addInterval('12:00', '14:00')
        ->addInterval('10:00', '13:30')
        ->addInterval('15:00', '17:30')
        ->calculate(); // "06:30:00"
?>
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Обычно ленивые так пишут ;)
PHP:
return sprintf('%02d:%02d:%02d', $h, $m, $s);
А это специально было, ТС-у кусочек темной магии ;) Типа, надо будет — придется разбираться ;)

Там вообще надо делать return array('hours' =>$h, 'minutes' => $m, 'seconds' => $s)
что бы потом нормально с этим дальше работать. Или даже просто возвращать секунды — их всегда можно пересчитать в что хочешь.
 

Redjik

Джедай-мастер
а можно было привести к unixtime - особо дата нам не важна, берем сегодняшний день
 

флоппик

promotor fidei
Команда форума
Партнер клуба

флоппик

promotor fidei
Команда форума
Партнер клуба
Хм - я имел ввиду strtotime - но ты и так через него сделал, правда 5 минут гугления показали способ попроще.
http://www.php.net/manual/en/dateinterval.construct.php
Ну, велкам показать готовое решение лучше? Ссылок на мануал-то и я могу кучу накидать. DateInterval-то тоже не умеет дырки в нескольких интервалах считать, и перекрывающиеся интервалы.
 
Сверху