我们为此使用了库Recurr。
我们的实体类看起来基本上像下面这样(它被剥离并且没有以这种方式测试,但它对我们的情况完美起作用)。我们只将它用于重复日期而不是时间,但使用我们的示例继续这个问题应该不是问题。
检查一下 - 因为我非常肯定这是一个尝试自己构建它的更多努力。
<?php
use Doctrine\ORM\Mapping as ORM;
use Recurr\Recurrence;
use Recurr\Rule;
use Recurr\Transformer\ArrayTransformer;
use Recurr\Transformer\ArrayTransformerConfig;
class Availability
{
private static $frequencyList = array(0 => 'DAILY', 1 => 'WEEKLY', 2 => 'MONTHLY', 3 => 'YEARLY');
private static $weekDays = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA');
/**
* @var ProductService
* @ORM\ManyToOne(targetEntity="YourBundle\Service", inversedBy="availabilities")
*/
private $service;
/**
* @var \DateTime - indicates 'first date' of recurring timeframe
* @ORM\Column(type="date", nullable=true)
*/
private $dateStart;
/**
* @var \DateTime - indicates 'until date' of rRule
* @ORM\Column(type="date", nullable=true)
*/
private $dateUntil;
/**
* @var int - indicates 'how often' rRule applies
* @ORM\Column(type="integer", nullable=true)
*/
private $count;
/**
* @var int - indicates 'how often' per frequency, ex. 1 means every month, 2 every other month
* @ORM\Column(type="integer", nullable=true, name="freq_interval")
*/
private $interval;
/**
* @var int - indicates 'frequency', uses self::$frequencyList
* @ORM\Column(type="integer", nullable=true)
*/
private $freq;
/**
* @var array - indicates 'every day', uses self::$weekDays
* @ORM\Column(type="simple_array", nullable=true)
*/
private $byDay;
/**
* @var array - integer indicates 'day of month', e.g. 1 is first day of month, -1 is last day
* @ORM\Column(type="simple_array", nullable=true)
*/
private $byMonthDay;
/**
* @var array - integer indicates 'day of year', e.g. 1 is first day of year, -1 is last day of year
* @ORM\Column(type="simple_array", nullable=true)
*/
private $byYearDay;
/**
* @var array - indicates 'every month' January is 0, December = 12
* @ORM\Column(type="simple_array", nullable=true)
*/
private $byMonth;
// ...getter and setter for all attributes HERE...
/**
* @return null|\DateTime[]
*/
public function getRecurrenceCollection()
{
if ($this->getDateEffective() !== null) {
return null;
}
if ($this->getFreq() === null) {
return null;
}
$result = array();
if ($this->getFreq() !== null) {
$rulePart[] = 'FREQ=' . self::$frequencyList[$this->getFreq()];
}
if ($this->getCount() !== null) {
$rulePart[] = 'COUNT=' . $this->getCount();
}
if ($this->getDateUntil() !== null) {
$rulePart[] = 'UNTIL=' . TimeUtil::canonicalDateFormat($this->getDateUntil());
}
if ($this->getInterval() === null) {
$rulePart[] = 'INTERVAL=1';
} else {
$rulePart[] = 'INTERVAL=' . $this->getInterval();
}
if (count($this->getByDay()) > 0) {
$byWeekDayArray = array();
foreach ($this->getByDay() as $byDay) {
$byWeekDayArray[] = self::$weekDays[$byDay];
}
$rulePart[] = 'BYDAY=' . implode(',', $byWeekDayArray);
}
if (count($this->getByMonth()) > 0) {
$rulePart[] = 'BYMONTH=' . implode(',', $this->getByMonth());
}
if (count($this->getByMonthDay()) > 0) {
$rulePart[] = 'BYMONTHDAY=' . implode(',', $this->getByMonthDay());
}
if (count($this->getByYearDay()) > 0) {
$rulePart[] = 'BYYEARDAY=' . implode(',', $this->getByYearDay());
}
$ruleString = implode(';', $rulePart);
$rule = new Rule($ruleString, $this->getDateStart(), null, 'UTC');
$transformer = new ArrayTransformer();
// enable fix for MONTHLY
if ($this->getFreq() === 2) {
$transformerConfig = new ArrayTransformerConfig();
$transformerConfig->enableLastDayOfMonthFix();
$transformer->setConfig($transformerConfig);
}
$elements = $transformer->transform($rule);
/** @var Recurrence $element */
foreach ($elements as $element) {
$result[] = $element->getEnd();
}
return $result;
}
}
我严重推荐使用一些像图书馆的优秀https://github.com/simshaun/recurr,而不是试图重新发明轮子。 – LBA
@LBA我想过了,但我无法弄清楚如何设置多个时间间隔,比如'从每个星期一的08:00到10:00和12:30到14:30' – blahblah
看我的示例中提供的答案 - 可以实现它。 – LBA