我們爲此使用了庫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