2

の形式でいくつかの日付範囲がありDateTime $begin, DateTime $endます。これらの範囲は、あらゆる方法で重複できます。

|-------|
               |=======|
           |------|
                     |======|
           |------------|
|=======|
  |---|

私がやろうとしているDateIntervalのは、最初の範囲の開始から最新の範囲の終わりまで (上記の場合は 4 番目) の範囲の長さ (秒または ) を取得することです。

範囲が 2 つしかない場合は問題ありませんが、範囲を 2 つ以上に拡張する方法がわかりません。

編集:

class Range {
    public DateTime $begin;
    public DateTime $end;
}

$ranges = getRanges(); # function that returns array of Range objects

function getActiveHours($_ranges = array()) {
  $sum = 0;
  # this is the function I'd like to have
  return $sum;
}

DateInterval2 つの範囲に対してのみ、オブジェクトを返す関数があります。

function addTimeRanges(DateTime $b1, DateTime $e1, DateTime $b2, DateTime $e2) {
    $res = null;
    if ($e1 < $b2 || $e2 < $b1) { # separate ranges
        $r1 = $b1->diff($e1);
        $r2 = $b2->diff($e2);
        $res = addIntervals($r1, $r2);
    } else if ($b1 <= $b2 && $e1 >= $e2) { # first range includes second
        $res = $b1->diff($e1);
    } else if ($b1 > $b2 && $e1 < $e2) { # second range includes first
        $res = $b2->diff($e2);
    } else if ($b1 < $b2 && $e1 <= $e2 && $b2 <= $e1) { # partial intersection
        $res = $b1->diff($e2);
    } else if ($b2 < $b1 && $e2 <= $e1 && $b1 <= $e2) { # partial intersection
        $res = $b2->diff($e1);
    }
    return $res;
}

whereは、2 つのオブジェクトの合計を別のオブジェクトとしてaddIntervals返す関数です。DateIntervalDateInterval

これはいくつかの基本的なバージョンです。私の製品コードでは、他の多くの無関係なものを使用しています。

簡単にするために、次の時間部分のみがあるとしましょうDateTime: ('06:00:00' から '08:00:00'), ('07:00:00' から '09:00:00'), ('06 :00:00', '08:00:00'), ('11:00:00' から '12:00:00') (このような範囲はたくさんあります)。今欲しい結果は4時間(6時から9時+11時から12時)です。

4

4 に答える 4

0
$ranges = array(
    array(date_create_from_format('U', 1364654958), date_create_from_format('U', 1364655758)), //800s (intersect with 2 row, 700s) = 100s
    array(date_create_from_format('U', 1364654658), date_create_from_format('U', 1364655658)), //1000s (intersect with 1 row)
    array(date_create_from_format('U', 1364656858), date_create_from_format('U', 1364656958)), //100s
);  //total 1200s = 20m
array_multisort($ranges, SORT_ASC, array_map(function($a){return $a[0];}, $ranges));
$count = count($ranges)-1;
for ($i=0; $i < $count; $i++) {
    if ($ranges[$i+1][0] < $ranges[$i][1]) {
        $ranges[$i][1] = max($ranges[$i][1], $ranges[$i+1][1]);
        unset($ranges[$i+1]);
        $i--;
        $count--;
    }
}
$sum = date_create();
foreach ($ranges as $value) {
    date_add($sum, date_diff($value[0],$value[1]));
}
print_r(date_diff(date_create(), $sum));
于 2013-03-30T15:04:31.890 に答える
0

与えられたタスクの例

class DateRange
{
    private $startDate;
    private $endDate;

    public function getStart(){
        return clone $this->startDate;
    }

    public function getEnd(){
        return clone $this->endDate;
    }

    public function __construct(\DateTime $startDate, \DateTime $endDate = null)
    {
        $this->startDate = $startDate;
        if (is_null($endDate)) {
            $this->endDate = new \DateTime();
        } else {
            $this->endDate = $endDate;
        }
    }
}

class DateRanges
{
    private $ranges = array();

    public function addRange(\DateRange $range)
    {
        $this->ranges[] = $range;
    }

    private function _RageToArray(\DateRange $_in)
    {
        $_r = array();
        $start = $_in->getStart();
        $end = $_in->getEnd();
        while($start<$end){
            $_r[$start->format('Y-m-d')] = null;
            $start->modify('+1 days');
        }
        return $_r;
    }

    public function getDaysCount()
    {
        $_r = array();

        foreach($this->ranges as $range){
            $_r += $this->_RageToArray($range);
        }
        return count($_r);
    }
}

$today = new DateTime();
$ranges = new DateRanges();

$x = new stdClass();
$x->start = (clone $today);
$x->start->modify('-3 years');
$x->end = (clone $x->start);
$x->end->modify('+1 month');
$ranges->addRange(new DateRange($x->start, $x->end));

$x = new stdClass();
$x->start = (clone $today);
$x->start->modify('-3 years');
$x->end = (clone $x->start);
$x->end->modify('+15 days');
$ranges->addRange(new DateRange($x->start, $x->end));

$x = new stdClass();
$x->start = (clone $today);
$x->start->modify('-4 years');
$x->end = (clone $x->start);
$x->end->modify('+15 days');
$ranges->addRange(new DateRange($x->start, $x->end));

echo $ranges->getDaysCount() . ' must be near ' . (31 + 15) . PHP_EOL;
于 2013-07-12T11:49:24.850 に答える