Я пытаюсь реализовать модель классов Мартина Фаулера для повторяющихся событий в PHP. Объекты DateTime и DatePeriod PHP выглядят так, как будто они хорошо подходят для работы с временными выражениями. Проблема в том, что мне нужно иметь возможность выполнять операции UNION, INTERSECT и DIFFERENCE над DatePeriods, чтобы я мог вычислять выражения типа «каждый вторник, кроме четных дат». В этом примере потребуется разность DatePeriod «каждый вторник» и DatePeriod «четная дата».
DatePeriod является итеративным, но он не доступен для стандартных функций обработки массивов, таких как array_intersect()
и array_diff()
. (Я хочу!) Поэтому я попытался изменить DatePeriod на массив с $ap=array_to_iterator($dp)
. Это работает в основном так, как ожидалось, за исключением того, что объекты DateTime, содержащиеся в DatePeriod, не имеют метода __toString()
, чего требуют многие функции массива.
Моя последняя попытка наиболее близка:
function recur_union($p1,$p2){
$a1=(is_object($p1)) ? iterator_to_array($p1):$p1;
$d_arr=recur_difference($p2,$a1);
return array_merge($a1,$d_arr);
}
function recur_difference($p1,$p2){
$arr=array();
$a2=(is_object($p2)) ? iterator_to_array($p2):$p2;
foreach($p1 as $dt){
if(!in_array($dt,$a2))$arr[]=$dt;
}
return $arr;
}
$p1=new DatePeriod(date_create('2008-01-01'),DateInterval::createFromDateString( "+2 days" ),date_create('2008-12-31'));
$p2=new DatePeriod(date_create('2008-01-01'),DateInterval::createFromDateString( "+7 days" ),date_create('2008-12-31'));
$au=recur_union($p1,$p2);
$ad=recur_difference($p1,$p2);
echo $au, $ad;
К сожалению, похоже, что DatePeriods $ p1 и $ p2 блокируются во время обработки. Если я сначала сделаю recur_union($p1,$p2)
, я получу правильный результат. Если сделано после recur_difference($p1,$p2)
, recur_union
возвращает пустой массив. То же самое происходит для recur_difference
.
Вопрос № 1: Кто-нибудь может объяснить, почему iterator_to_array
, кажется, стирает первоначальный DatePeriod?
Так как мои DatePeriods были забиты, я решил попробовать их клонировать. Но следующее заставляет IE8 отображать сообщение «не удается отобразить веб-страницу», а FF3.5 ничего не делает:
$p1=new DatePeriod(date_create('2008-01-01'),DateInterval::createFromDateString( "+2 days" ),date_create('2008-12-31'));
$p2=new DatePeriod(date_create('2008-01-01'),DateInterval::createFromDateString( "+7 days" ),date_create('2008-12-31'));
$a1=clone $p1;
$a2=clone $p2;
$au=recur_union($p1,$p2);
$ad=recur_difference($a1,$a2);
echo $au, $ad;
Вопрос № 2: Что происходит с клонами?
Спасибо всем!