<?php
class Period
{
protected $start;
protected $end;
public function __construct($start, $end)
{
$this->start = $start;
$this->end = $end;
}
public function getStart()
{
return $this->start;
}
public function getEnd()
{
return $this->end;
}
public function containsTime($time)
{
return $this->start <= $time && $this->end > $time;
}
public function containsPeriod(Period $period)
{
return $this->containsTime($period->getStart()) &&
$this->containsTime($period->getEnd());
}
public function overlaps(Period $period)
{
return $this->containsTime($period->getStart()) ||
$this->containsTime($period->getEnd()) ||
$period->containsTime($this->start);
}
public function intersect(Period $other)
{
$ts = $this->start;
$os = $other->start;
$te = $this->end;
$oe = $other->end;
if ($this->containsTime($os)) {
$start = $os;
} else if ($other->containsTime($ts)) {
$start = $ts;
} else {
return null;
}
if ($this->containsTime($oe)) {
$end = $oe;
} else if ($other->containsTime($te)) {
$end = $te;
} else {
return null;
}
return new Period($start, $end);
}
}
class Availability
{
protected $periods;
public function __construct($periods)
{
$this->periods = $periods;
}
public function getPeriods(Period $range)
{
return array_filter($this->periods, function ($period) use ($range) {
return $range->intersect($period);
});
}
}
function st($s)
{
return strtotime($s);
}
function pd($s1, $s2)
{
return new Period(st($s1), st($s2));
}
function av()
{
$p = func_get_args();
$p = array_map(function ($p) {
return pd($p[0], $p[1]);
}, $p);
return new Availability($p);
}
function sTime($time)
{
return date('j.M.H:i:s', $time);
}
function strPeriod(Period $period)
{
return sprintf('%s - %s', sTime($period->getStart()), sTime($period->getEnd()));
}
function strResults($periods)
{
return implode(PHP_EOL, array_map('strPeriod', $periods));
}
$availabilities = [
av(
// Fridays between noon and 6pm
['2018-10-05 12:00:00', '2018-10-05 18:00:00'],
['2018-10-12 12:00:00', '2018-10-12 18:00:00'],
['2018-10-19 12:00:00', '2018-10-19 18:00:00'],
['2018-10-26 12:00:00', '2018-10-26 18:00:00']
),
av(
// 15th till 19th full days
['2018-10-15 00:00:00', '2018-10-16 00:00:00'],
['2018-10-16 00:00:00', '2018-10-17 00:00:00'],
['2018-10-17 00:00:00', '2018-10-18 00:00:00'],
['2018-10-18 00:00:00', '2018-10-19 00:00:00'],
['2018-10-19 00:00:00', '2018-10-20 00:00:00']
),
av(
// Wed 10th, Fri 19th and Wed 24th between 8am and 2pm
['2018-10-10 08:00:00', '2018-10-10 14:00:00'],
['2018-10-19 08:00:00', '2018-10-19 14:00:00'],
['2018-10-24 08:00:00', '2018-10-24 14:00:00']
),
];
// Get periods for the whole month of October
$periods = [
pd('2018-10-01 00:00:00', '2018-11-01 00:00:00')
];
foreach ($availabilities as $i => $avail) {
printf('Availability #%d' . PHP_EOL, $i);
$tPeriods = [];
foreach ($periods as $period) {
printf(' > Getting available periods in %s'.PHP_EOL, strPeriod($period));
$aPeriods = $avail->getPeriods($period);
printf(' > Got %d periods'.PHP_EOL, count($aPeriods));
$tPeriods = array_merge($tPeriods, $aPeriods);
}
$periods = $tPeriods;
echo str_repeat('-', 80) . PHP_EOL;
}
echo str_repeat('=', 80) . PHP_EOL;
echo 'RESULTS:' . PHP_EOL;
echo strResults($periods);
preferences:
56.07 ms | 402 KiB | 5 Q