如何在PHP中分离两个时间范围数组?
我有两个数组:
状况
[0] => Array
(
[dateTimeStart] => 2016-07-21 00:00:00
[dateTimeEnd] => 2016-07-21 15:00:00
)
[3] => Array
(
[dateTimeStart] => 2016-07-21 17:00:00
[dateTimeEnd] => 2016-07-21 19:30:00
)
日期
[0] => Array
(
[dateTimeStart] => 2016-07-21 08:00:00
[dateTimeEnd] => 2016-07-21 12:00:00
)
[1] => Array
(
[dateTimeStart] => 2016-07-21 18:30:00
[dateTimeEnd] => 2016-07-21 19:30:00
)
我已将所有日期与可用性分开。如果你无法理解我所说的话,这就是退出这一分离时我应该拥有的:
[0] => Array
(
[dateTimeStart] => 2016-07-21 00:00:00
[dateTimeEnd] => 2016-07-21 8:00:00
)
[1] => Array
(
[dateTimeStart] => 2016-07-21 12:00:00
[dateTimeEnd] => 2016-07-21 15:00:00
)
[2] => Array
(
[dateTimeStart] => 2016-07-21 17:00:00
[dateTimeEnd] => 2016-07-21 18:30:00
)
它可能是偶数范围,而不仅仅是在一天之内
[dateTimeStart] => 2016-07-21 17:00:00
[dateTimeEnd] => 2016-07-22 01:30:00
。请帮助我或显示我必须去的地方。
答案 0 :(得分:1)
如splash58 commented所示,这是hakre's answer对此问题的演示:
$shift = new Ranges([
new Range(new DateTime('2016-07-21 00:00:00'), new DateTime('2016-07-21 15:00:00')),
new Range(new DateTime('2016-07-21 17:00:00'), new DateTime('2016-07-21 19:30:00')),
]);
$unavailables = new Ranges([
new Range(new DateTime('2016-07-21 08:00:00'), new DateTime('2016-07-21 12:00:00')),
new Range(new DateTime('2016-07-21 18:30:00'), new DateTime('2016-07-21 19:30:00')),
]);
print_r($shift);
Ranges Object ( [ranges:protected] => Array ( [0] => Range Object ( [start:protected] => DateTime Object ( [date] => 2016-07-21 00:00:00 [timezone_type] => 3 [timezone] => America/Chicago ) [end:protected] => DateTime Object ( [date] => 2016-07-21 08:00:00 [timezone_type] => 3 [timezone] => America/Chicago ) ) [1] => Range Object ( [start:protected] => DateTime Object ( [date] => 2016-07-21 12:00:00 [timezone_type] => 3 [timezone] => America/Chicago ) [end:protected] => DateTime Object ( [date] => 2016-07-21 15:00:00 [timezone_type] => 3 [timezone] => America/Chicago ) ) [2] => Range Object ( [start:protected] => DateTime Object ( [date] => 2016-07-21 17:00:00 [timezone_type] => 3 [timezone] => America/Chicago ) [end:protected] => DateTime Object ( [date] => 2016-07-21 18:30:00 [timezone_type] => 3 [timezone] => America/Chicago ) ) ) )
如果the source code被破坏,请参考the link以供参考。
/**
* @link https://stackoverflow.com/questions/13129336/split-a-time-range-into-pieces-by-other-time-ranges
* @link https://gist.github.com/gists/3977645
* @author hakre
*/
class Range
{
/**
* @var DateTime
*/
protected $start;
/**
* @var DateTime
*/
protected $end;
public function __construct(DateTime $start, DateTime $end) {
$this->setStart($start);
$this->setEnd($end);
}
/**
* @return DateTime
*/
public function getStart() {
return $this->start;
}
public function setStart(DateTime $start) {
$this->start = $start;
}
/**
* @return \DateTime
*/
public function getEnd() {
return $this->end;
}
/**
* @param DateTime $end
* @throws InvalidArgumentException
*/
public function setEnd(DateTime $end) {
if ($end < $this->start) {
throw new InvalidArgumentException('End before Start');
}
$this->end = $end;
}
public function hasTime(DateTime $time) {
return $this->start <= $time and $this->end >= $time;
}
public function hasContact(Range $range) {
return $this->hasTime($range->start)
or $this->hasTime($range->end);
}
public function isSame(Range $range) {
return $this->start == $range->start
and $this->end == $range->end;
}
public function isWithin(Range $range) {
return $range->start > $this->start
and $range->end < $this->end;
}
public function isSubset(Range $range) {
return $range->hasTime($this->start)
and $range->hasTime($this->end);
}
public function add(Range $range) {
if (!$this->hasContact($range)) {
throw new InvalidArgumentException('Range needs to overlap.');
}
if ($range->start < $this->start) {
$this->start = $range->start;
}
if ($range->end > $this->end) {
$this->end = $range->end;
}
}
public function substract(Range $range) {
if ($this->isWithIn($range)) {
throw new InvalidArgumentException('Range would divide.');
}
if ($this->isSubset($range)) {
throw new InvalidArgumentException('Range would delete.');
}
if (!$this->hasContact($range)) {
return;
}
if ($range->start == $this->start) {
$this->start = $range->end;
return;
}
if ($range->end == $this->end) {
$this->end = $range->start;
return;
}
if ($range->start < $this->end) {
$this->end = $range->start;
} elseif ($range->end > $this->start) {
$this->start = $range->end;
}
}
public function getDifferenceArray(Range $range) {
if ($this->isSubset($range)) {
return [];
}
if (!$this->hasContact($range)) {
return [clone $this];
}
if ($this->isWithin($range)) {
$result[1] = clone $result[0] = clone $this;
$result[0]->end = $range->start;
$result[1]->start = $range->end;
return $result;
}
$result = clone $this;
$result->substract($range);
return [$result];
}
public function format($format) {
return [
$this->start->format($format),
$this->end->format($format)
];
}
}
class Ranges implements IteratorAggregate, Countable
{
protected $ranges = [];
public function __construct($ranges = NULL, DateTime $end = NULL) {
if ($ranges) {
if ($ranges instanceof DateTime) {
if (null === $end) {
throw new InvalidArgumentException('Need start and end.');
}
$ranges = new Range($ranges, $end);
}
if ($ranges instanceof Range) {
$ranges = [$ranges];
}
foreach ($ranges as $range) {
$this->append($range);
}
}
}
public function getStart() {
if (!$this->ranges) {
throw new BadMethodCallException('Enpty Range');
}
return $this->ranges[0]->getStart();
}
public function getEnd() {
if (!$this->ranges) {
throw new BadMethodCallException('Enpty Range');
}
return $this->ranges[count($this->ranges) - 1]->getEnd();
}
public function append(Range $range) {
if ($this->ranges) {
if ($range->getStart() <= $this->getEnd()) {
throw new InvalidArgumentException('Can not append Range that is inside ranged time already');
}
}
$this->ranges[] = $range;
}
/**
* @param Range $range
* @return Ranges
*/
public function substractRange(Range $range) {
$result = new self();
foreach ($this as $member) {
/* @var Range $member */
foreach ($member->getDifferenceArray($range) as $new) {
$result->append($new);
}
}
$this->ranges = $result->ranges;
}
public function substract(Ranges $ranges) {
$result = clone $this;
foreach ($ranges as $range) {
$result->substractRange($range);
}
$this->ranges = $result->ranges;
}
public function getIterator() {
return new ArrayIterator($this->ranges);
}
public function getRange() {
return new Range($this->getStart(), $this->getEnd());
}
public function count() {
return count($this->ranges);
}
}