1<?php 2 3namespace Sabre\VObject\Recur\EventIterator; 4 5use DateTimeImmutable; 6use DateTimeZone; 7use Sabre\VObject\Component\VCalendar; 8use Sabre\VObject\Recur\EventIterator; 9 10class MainTest extends \PHPUnit_Framework_TestCase { 11 12 function testValues() { 13 14 $vcal = new VCalendar(); 15 $ev = $vcal->createComponent('VEVENT'); 16 $ev->UID = 'bla'; 17 $ev->RRULE = 'FREQ=DAILY;BYHOUR=10;BYMINUTE=5;BYSECOND=16;BYWEEKNO=32;BYYEARDAY=100,200'; 18 $dtStart = $vcal->createProperty('DTSTART'); 19 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07')); 20 21 $ev->add($dtStart); 22 23 $vcal->add($ev); 24 25 $it = new EventIterator($vcal, (string)$ev->UID); 26 27 $this->assertTrue($it->isInfinite()); 28 29 } 30 31 /** 32 * @expectedException \Sabre\VObject\InvalidDataException 33 * @depends testValues 34 */ 35 function testInvalidFreq() { 36 37 $vcal = new VCalendar(); 38 $ev = $vcal->createComponent('VEVENT'); 39 $ev->RRULE = 'FREQ=SMONTHLY;INTERVAL=3;UNTIL=20111025T000000Z'; 40 $ev->UID = 'foo'; 41 $dtStart = $vcal->createProperty('DTSTART'); 42 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 43 44 $ev->add($dtStart); 45 $vcal->add($ev); 46 47 $it = new EventIterator($vcal, (string)$ev->UID); 48 49 } 50 51 /** 52 * @expectedException InvalidArgumentException 53 */ 54 function testVCalendarNoUID() { 55 56 $vcal = new VCalendar(); 57 $it = new EventIterator($vcal); 58 59 } 60 61 /** 62 * @expectedException InvalidArgumentException 63 */ 64 function testVCalendarInvalidUID() { 65 66 $vcal = new VCalendar(); 67 $it = new EventIterator($vcal, 'foo'); 68 69 } 70 71 /** 72 * @depends testValues 73 */ 74 function testHourly() { 75 76 $vcal = new VCalendar(); 77 $ev = $vcal->createComponent('VEVENT'); 78 79 $ev->UID = 'bla'; 80 $ev->RRULE = 'FREQ=HOURLY;INTERVAL=3;UNTIL=20111025T000000Z'; 81 $dtStart = $vcal->createProperty('DTSTART'); 82 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07 12:00:00', new DateTimeZone('UTC'))); 83 84 $ev->add($dtStart); 85 $vcal->add($ev); 86 87 $it = new EventIterator($vcal, $ev->UID); 88 89 // Max is to prevent overflow 90 $max = 12; 91 $result = []; 92 foreach ($it as $item) { 93 94 $result[] = $item; 95 $max--; 96 97 if (!$max) break; 98 99 } 100 101 $tz = new DateTimeZone('UTC'); 102 103 $this->assertEquals( 104 [ 105 new DateTimeImmutable('2011-10-07 12:00:00', $tz), 106 new DateTimeImmutable('2011-10-07 15:00:00', $tz), 107 new DateTimeImmutable('2011-10-07 18:00:00', $tz), 108 new DateTimeImmutable('2011-10-07 21:00:00', $tz), 109 new DateTimeImmutable('2011-10-08 00:00:00', $tz), 110 new DateTimeImmutable('2011-10-08 03:00:00', $tz), 111 new DateTimeImmutable('2011-10-08 06:00:00', $tz), 112 new DateTimeImmutable('2011-10-08 09:00:00', $tz), 113 new DateTimeImmutable('2011-10-08 12:00:00', $tz), 114 new DateTimeImmutable('2011-10-08 15:00:00', $tz), 115 new DateTimeImmutable('2011-10-08 18:00:00', $tz), 116 new DateTimeImmutable('2011-10-08 21:00:00', $tz), 117 ], 118 $result 119 ); 120 121 } 122 123 /** 124 * @depends testValues 125 */ 126 function testDaily() { 127 128 $vcal = new VCalendar(); 129 $ev = $vcal->createComponent('VEVENT'); 130 131 $ev->UID = 'bla'; 132 $ev->RRULE = 'FREQ=DAILY;INTERVAL=3;UNTIL=20111025T000000Z'; 133 $dtStart = $vcal->createProperty('DTSTART'); 134 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 135 136 $ev->add($dtStart); 137 138 $vcal->add($ev); 139 140 $it = new EventIterator($vcal, $ev->UID); 141 142 // Max is to prevent overflow 143 $max = 12; 144 $result = []; 145 foreach ($it as $item) { 146 147 $result[] = $item; 148 $max--; 149 150 if (!$max) break; 151 152 } 153 154 $tz = new DateTimeZone('UTC'); 155 156 $this->assertEquals( 157 [ 158 new DateTimeImmutable('2011-10-07', $tz), 159 new DateTimeImmutable('2011-10-10', $tz), 160 new DateTimeImmutable('2011-10-13', $tz), 161 new DateTimeImmutable('2011-10-16', $tz), 162 new DateTimeImmutable('2011-10-19', $tz), 163 new DateTimeImmutable('2011-10-22', $tz), 164 new DateTimeImmutable('2011-10-25', $tz), 165 ], 166 $result 167 ); 168 169 } 170 171 /** 172 * @depends testValues 173 */ 174 function testNoRRULE() { 175 176 $vcal = new VCalendar(); 177 $ev = $vcal->createComponent('VEVENT'); 178 179 $ev->UID = 'bla'; 180 $dtStart = $vcal->createProperty('DTSTART'); 181 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 182 183 $ev->add($dtStart); 184 185 $vcal->add($ev); 186 187 $it = new EventIterator($vcal, $ev->UID); 188 189 // Max is to prevent overflow 190 $max = 12; 191 $result = []; 192 foreach ($it as $item) { 193 194 $result[] = $item; 195 $max--; 196 197 if (!$max) break; 198 199 } 200 201 $tz = new DateTimeZone('UTC'); 202 203 $this->assertEquals( 204 [ 205 new DateTimeImmutable('2011-10-07', $tz), 206 ], 207 $result 208 ); 209 210 } 211 212 /** 213 * @depends testValues 214 */ 215 function testDailyByDayByHour() { 216 217 $vcal = new VCalendar(); 218 $ev = $vcal->createComponent('VEVENT'); 219 220 $ev->UID = 'bla'; 221 $ev->RRULE = 'FREQ=DAILY;BYDAY=SA,SU;BYHOUR=6,7'; 222 $dtStart = $vcal->createProperty('DTSTART'); 223 $dtStart->setDateTime(new DateTimeImmutable('2011-10-08 06:00:00', new DateTimeZone('UTC'))); 224 225 $ev->add($dtStart); 226 227 $vcal->add($ev); 228 229 $it = new EventIterator($vcal, (string)$ev->UID); 230 231 // Grabbing the next 12 items 232 $max = 12; 233 $result = []; 234 foreach ($it as $item) { 235 236 $result[] = $item; 237 $max--; 238 239 if (!$max) break; 240 241 } 242 243 $tz = new DateTimeZone('UTC'); 244 245 $this->assertEquals( 246 [ 247 new DateTimeImmutable('2011-10-08 06:00:00', $tz), 248 new DateTimeImmutable('2011-10-08 07:00:00', $tz), 249 new DateTimeImmutable('2011-10-09 06:00:00', $tz), 250 new DateTimeImmutable('2011-10-09 07:00:00', $tz), 251 new DateTimeImmutable('2011-10-15 06:00:00', $tz), 252 new DateTimeImmutable('2011-10-15 07:00:00', $tz), 253 new DateTimeImmutable('2011-10-16 06:00:00', $tz), 254 new DateTimeImmutable('2011-10-16 07:00:00', $tz), 255 new DateTimeImmutable('2011-10-22 06:00:00', $tz), 256 new DateTimeImmutable('2011-10-22 07:00:00', $tz), 257 new DateTimeImmutable('2011-10-23 06:00:00', $tz), 258 new DateTimeImmutable('2011-10-23 07:00:00', $tz), 259 ], 260 $result 261 ); 262 263 } 264 265 /** 266 * @depends testValues 267 */ 268 function testDailyByHour() { 269 270 $vcal = new VCalendar(); 271 $ev = $vcal->createComponent('VEVENT'); 272 273 $ev->UID = 'bla'; 274 $ev->RRULE = 'FREQ=DAILY;INTERVAL=2;BYHOUR=10,11,12,13,14,15'; 275 $dtStart = $vcal->createProperty('DTSTART'); 276 $dtStart->setDateTime(new DateTimeImmutable('2012-10-11 12:00:00', new DateTimeZone('UTC'))); 277 278 $ev->add($dtStart); 279 280 $vcal->add($ev); 281 282 $it = new EventIterator($vcal, (string)$ev->UID); 283 284 // Grabbing the next 12 items 285 $max = 12; 286 $result = []; 287 foreach ($it as $item) { 288 289 $result[] = $item; 290 $max--; 291 292 if (!$max) break; 293 294 } 295 296 $tz = new DateTimeZone('UTC'); 297 298 $this->assertEquals( 299 [ 300 new DateTimeImmutable('2012-10-11 12:00:00', $tz), 301 new DateTimeImmutable('2012-10-11 13:00:00', $tz), 302 new DateTimeImmutable('2012-10-11 14:00:00', $tz), 303 new DateTimeImmutable('2012-10-11 15:00:00', $tz), 304 new DateTimeImmutable('2012-10-13 10:00:00', $tz), 305 new DateTimeImmutable('2012-10-13 11:00:00', $tz), 306 new DateTimeImmutable('2012-10-13 12:00:00', $tz), 307 new DateTimeImmutable('2012-10-13 13:00:00', $tz), 308 new DateTimeImmutable('2012-10-13 14:00:00', $tz), 309 new DateTimeImmutable('2012-10-13 15:00:00', $tz), 310 new DateTimeImmutable('2012-10-15 10:00:00', $tz), 311 new DateTimeImmutable('2012-10-15 11:00:00', $tz), 312 ], 313 $result 314 ); 315 316 } 317 318 /** 319 * @depends testValues 320 */ 321 function testDailyByDay() { 322 323 $vcal = new VCalendar(); 324 $ev = $vcal->createComponent('VEVENT'); 325 326 $ev->UID = 'bla'; 327 $ev->RRULE = 'FREQ=DAILY;INTERVAL=2;BYDAY=TU,WE,FR'; 328 $dtStart = $vcal->createProperty('DTSTART'); 329 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 330 331 $ev->add($dtStart); 332 333 $vcal->add($ev); 334 335 $it = new EventIterator($vcal, (string)$ev->UID); 336 337 // Grabbing the next 12 items 338 $max = 12; 339 $result = []; 340 foreach ($it as $item) { 341 342 $result[] = $item; 343 $max--; 344 345 if (!$max) break; 346 347 } 348 349 $tz = new DateTimeZone('UTC'); 350 351 $this->assertEquals( 352 [ 353 new DateTimeImmutable('2011-10-07', $tz), 354 new DateTimeImmutable('2011-10-11', $tz), 355 new DateTimeImmutable('2011-10-19', $tz), 356 new DateTimeImmutable('2011-10-21', $tz), 357 new DateTimeImmutable('2011-10-25', $tz), 358 new DateTimeImmutable('2011-11-02', $tz), 359 new DateTimeImmutable('2011-11-04', $tz), 360 new DateTimeImmutable('2011-11-08', $tz), 361 new DateTimeImmutable('2011-11-16', $tz), 362 new DateTimeImmutable('2011-11-18', $tz), 363 new DateTimeImmutable('2011-11-22', $tz), 364 new DateTimeImmutable('2011-11-30', $tz), 365 ], 366 $result 367 ); 368 369 } 370 371 /** 372 * @depends testValues 373 */ 374 function testWeekly() { 375 376 $vcal = new VCalendar(); 377 $ev = $vcal->createComponent('VEVENT'); 378 379 $ev->UID = 'bla'; 380 $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;COUNT=10'; 381 $dtStart = $vcal->createProperty('DTSTART'); 382 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 383 384 $ev->add($dtStart); 385 386 $vcal->add($ev); 387 388 $it = new EventIterator($vcal, (string)$ev->UID); 389 390 // Max is to prevent overflow 391 $max = 12; 392 $result = []; 393 foreach ($it as $item) { 394 395 $result[] = $item; 396 $max--; 397 398 if (!$max) break; 399 400 } 401 402 $tz = new DateTimeZone('UTC'); 403 404 $this->assertEquals( 405 [ 406 new DateTimeImmutable('2011-10-07', $tz), 407 new DateTimeImmutable('2011-10-21', $tz), 408 new DateTimeImmutable('2011-11-04', $tz), 409 new DateTimeImmutable('2011-11-18', $tz), 410 new DateTimeImmutable('2011-12-02', $tz), 411 new DateTimeImmutable('2011-12-16', $tz), 412 new DateTimeImmutable('2011-12-30', $tz), 413 new DateTimeImmutable('2012-01-13', $tz), 414 new DateTimeImmutable('2012-01-27', $tz), 415 new DateTimeImmutable('2012-02-10', $tz), 416 ], 417 $result 418 ); 419 420 } 421 422 /** 423 * @depends testValues 424 */ 425 function testWeeklyByDayByHour() { 426 427 $vcal = new VCalendar(); 428 $ev = $vcal->createComponent('VEVENT'); 429 430 $ev->UID = 'bla'; 431 $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=MO;BYHOUR=8,9,10'; 432 $dtStart = $vcal->createProperty('DTSTART'); 433 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07 08:00:00', new DateTimeZone('UTC'))); 434 435 $ev->add($dtStart); 436 437 $vcal->add($ev); 438 439 $it = new EventIterator($vcal, (string)$ev->UID); 440 441 // Grabbing the next 12 items 442 $max = 15; 443 $result = []; 444 foreach ($it as $item) { 445 446 $result[] = $item; 447 $max--; 448 449 if (!$max) break; 450 451 } 452 453 $tz = new DateTimeZone('UTC'); 454 455 $this->assertEquals( 456 [ 457 new DateTimeImmutable('2011-10-07 08:00:00', $tz), 458 new DateTimeImmutable('2011-10-07 09:00:00', $tz), 459 new DateTimeImmutable('2011-10-07 10:00:00', $tz), 460 new DateTimeImmutable('2011-10-18 08:00:00', $tz), 461 new DateTimeImmutable('2011-10-18 09:00:00', $tz), 462 new DateTimeImmutable('2011-10-18 10:00:00', $tz), 463 new DateTimeImmutable('2011-10-19 08:00:00', $tz), 464 new DateTimeImmutable('2011-10-19 09:00:00', $tz), 465 new DateTimeImmutable('2011-10-19 10:00:00', $tz), 466 new DateTimeImmutable('2011-10-21 08:00:00', $tz), 467 new DateTimeImmutable('2011-10-21 09:00:00', $tz), 468 new DateTimeImmutable('2011-10-21 10:00:00', $tz), 469 new DateTimeImmutable('2011-11-01 08:00:00', $tz), 470 new DateTimeImmutable('2011-11-01 09:00:00', $tz), 471 new DateTimeImmutable('2011-11-01 10:00:00', $tz), 472 ], 473 $result 474 ); 475 476 } 477 478 /** 479 * @depends testValues 480 */ 481 function testWeeklyByDaySpecificHour() { 482 483 $vcal = new VCalendar(); 484 $ev = $vcal->createComponent('VEVENT'); 485 486 $ev->UID = 'bla'; 487 $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=SU'; 488 $dtStart = $vcal->createProperty('DTSTART'); 489 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07 18:00:00', new DateTimeZone('UTC'))); 490 491 $ev->add($dtStart); 492 493 $vcal->add($ev); 494 495 $it = new EventIterator($vcal, (string)$ev->UID); 496 497 // Grabbing the next 12 items 498 $max = 12; 499 $result = []; 500 foreach ($it as $item) { 501 502 $result[] = $item; 503 $max--; 504 505 if (!$max) break; 506 507 } 508 509 $tz = new DateTimeZone('UTC'); 510 511 $this->assertEquals( 512 [ 513 new DateTimeImmutable('2011-10-07 18:00:00', $tz), 514 new DateTimeImmutable('2011-10-18 18:00:00', $tz), 515 new DateTimeImmutable('2011-10-19 18:00:00', $tz), 516 new DateTimeImmutable('2011-10-21 18:00:00', $tz), 517 new DateTimeImmutable('2011-11-01 18:00:00', $tz), 518 new DateTimeImmutable('2011-11-02 18:00:00', $tz), 519 new DateTimeImmutable('2011-11-04 18:00:00', $tz), 520 new DateTimeImmutable('2011-11-15 18:00:00', $tz), 521 new DateTimeImmutable('2011-11-16 18:00:00', $tz), 522 new DateTimeImmutable('2011-11-18 18:00:00', $tz), 523 new DateTimeImmutable('2011-11-29 18:00:00', $tz), 524 new DateTimeImmutable('2011-11-30 18:00:00', $tz), 525 ], 526 $result 527 ); 528 529 } 530 531 /** 532 * @depends testValues 533 */ 534 function testWeeklyByDay() { 535 536 $vcal = new VCalendar(); 537 $ev = $vcal->createComponent('VEVENT'); 538 539 $ev->UID = 'bla'; 540 $ev->RRULE = 'FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,WE,FR;WKST=SU'; 541 $dtStart = $vcal->createProperty('DTSTART'); 542 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 543 544 $ev->add($dtStart); 545 546 $vcal->add($ev); 547 548 $it = new EventIterator($vcal, (string)$ev->UID); 549 550 // Grabbing the next 12 items 551 $max = 12; 552 $result = []; 553 foreach ($it as $item) { 554 555 $result[] = $item; 556 $max--; 557 558 if (!$max) break; 559 560 } 561 562 $tz = new DateTimeZone('UTC'); 563 564 $this->assertEquals( 565 [ 566 new DateTimeImmutable('2011-10-07', $tz), 567 new DateTimeImmutable('2011-10-18', $tz), 568 new DateTimeImmutable('2011-10-19', $tz), 569 new DateTimeImmutable('2011-10-21', $tz), 570 new DateTimeImmutable('2011-11-01', $tz), 571 new DateTimeImmutable('2011-11-02', $tz), 572 new DateTimeImmutable('2011-11-04', $tz), 573 new DateTimeImmutable('2011-11-15', $tz), 574 new DateTimeImmutable('2011-11-16', $tz), 575 new DateTimeImmutable('2011-11-18', $tz), 576 new DateTimeImmutable('2011-11-29', $tz), 577 new DateTimeImmutable('2011-11-30', $tz), 578 ], 579 $result 580 ); 581 582 } 583 584 /** 585 * @depends testValues 586 */ 587 function testMonthly() { 588 589 $vcal = new VCalendar(); 590 $ev = $vcal->createComponent('VEVENT'); 591 592 $ev->UID = 'bla'; 593 $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=3;COUNT=5'; 594 $dtStart = $vcal->createProperty('DTSTART'); 595 $dtStart->setDateTime(new DateTimeImmutable('2011-12-05', new DateTimeZone('UTC'))); 596 597 $ev->add($dtStart); 598 599 $vcal->add($ev); 600 601 $it = new EventIterator($vcal, (string)$ev->UID); 602 603 $max = 14; 604 $result = []; 605 foreach ($it as $item) { 606 607 $result[] = $item; 608 $max--; 609 610 if (!$max) break; 611 612 } 613 614 $tz = new DateTimeZone('UTC'); 615 616 $this->assertEquals( 617 [ 618 new DateTimeImmutable('2011-12-05', $tz), 619 new DateTimeImmutable('2012-03-05', $tz), 620 new DateTimeImmutable('2012-06-05', $tz), 621 new DateTimeImmutable('2012-09-05', $tz), 622 new DateTimeImmutable('2012-12-05', $tz), 623 ], 624 $result 625 ); 626 627 628 } 629 630 /** 631 * @depends testValues 632 */ 633 function testMonthlyEndOfMonth() { 634 635 $vcal = new VCalendar(); 636 $ev = $vcal->createComponent('VEVENT'); 637 638 $ev->UID = 'bla'; 639 $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=12'; 640 $dtStart = $vcal->createProperty('DTSTART'); 641 $dtStart->setDateTime(new DateTimeImmutable('2011-12-31', new DateTimeZone('UTC'))); 642 643 $ev->add($dtStart); 644 645 $vcal->add($ev); 646 647 $it = new EventIterator($vcal, (string)$ev->UID); 648 649 $max = 14; 650 $result = []; 651 foreach ($it as $item) { 652 653 $result[] = $item; 654 $max--; 655 656 if (!$max) break; 657 658 } 659 660 $tz = new DateTimeZone('UTC'); 661 662 $this->assertEquals( 663 [ 664 new DateTimeImmutable('2011-12-31', $tz), 665 new DateTimeImmutable('2012-08-31', $tz), 666 new DateTimeImmutable('2012-10-31', $tz), 667 new DateTimeImmutable('2012-12-31', $tz), 668 new DateTimeImmutable('2013-08-31', $tz), 669 new DateTimeImmutable('2013-10-31', $tz), 670 new DateTimeImmutable('2013-12-31', $tz), 671 new DateTimeImmutable('2014-08-31', $tz), 672 new DateTimeImmutable('2014-10-31', $tz), 673 new DateTimeImmutable('2014-12-31', $tz), 674 new DateTimeImmutable('2015-08-31', $tz), 675 new DateTimeImmutable('2015-10-31', $tz), 676 ], 677 $result 678 ); 679 680 681 } 682 683 /** 684 * @depends testValues 685 */ 686 function testMonthlyByMonthDay() { 687 688 $vcal = new VCalendar(); 689 $ev = $vcal->createComponent('VEVENT'); 690 691 $ev->UID = 'bla'; 692 $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=5;COUNT=9;BYMONTHDAY=1,31,-7'; 693 $dtStart = $vcal->createProperty('DTSTART'); 694 $dtStart->setDateTime(new DateTimeImmutable('2011-01-01', new DateTimeZone('UTC'))); 695 696 $ev->add($dtStart); 697 698 $vcal->add($ev); 699 700 $it = new EventIterator($vcal, (string)$ev->UID); 701 702 $max = 14; 703 $result = []; 704 foreach ($it as $item) { 705 706 $result[] = $item; 707 $max--; 708 709 if (!$max) break; 710 711 } 712 713 $tz = new DateTimeZone('UTC'); 714 715 $this->assertEquals( 716 [ 717 new DateTimeImmutable('2011-01-01', $tz), 718 new DateTimeImmutable('2011-01-25', $tz), 719 new DateTimeImmutable('2011-01-31', $tz), 720 new DateTimeImmutable('2011-06-01', $tz), 721 new DateTimeImmutable('2011-06-24', $tz), 722 new DateTimeImmutable('2011-11-01', $tz), 723 new DateTimeImmutable('2011-11-24', $tz), 724 new DateTimeImmutable('2012-04-01', $tz), 725 new DateTimeImmutable('2012-04-24', $tz), 726 ], 727 $result 728 ); 729 730 } 731 732 /** 733 * A pretty slow test. Had to be marked as 'medium' for phpunit to not die 734 * after 1 second. Would be good to optimize later. 735 * 736 * @depends testValues 737 * @medium 738 */ 739 function testMonthlyByDay() { 740 741 $vcal = new VCalendar(); 742 $ev = $vcal->createComponent('VEVENT'); 743 744 $ev->UID = 'bla'; 745 $ev->RRULE = 'FREQ=MONTHLY;INTERVAL=2;COUNT=16;BYDAY=MO,-2TU,+1WE,3TH'; 746 $dtStart = $vcal->createProperty('DTSTART'); 747 $dtStart->setDateTime(new DateTimeImmutable('2011-01-03', new DateTimeZone('UTC'))); 748 749 $ev->add($dtStart); 750 751 $vcal->add($ev); 752 753 $it = new EventIterator($vcal, (string)$ev->UID); 754 755 $max = 20; 756 $result = []; 757 foreach ($it as $item) { 758 759 $result[] = $item; 760 $max--; 761 762 if (!$max) break; 763 764 } 765 766 $tz = new DateTimeZone('UTC'); 767 768 $this->assertEquals( 769 [ 770 new DateTimeImmutable('2011-01-03', $tz), 771 new DateTimeImmutable('2011-01-05', $tz), 772 new DateTimeImmutable('2011-01-10', $tz), 773 new DateTimeImmutable('2011-01-17', $tz), 774 new DateTimeImmutable('2011-01-18', $tz), 775 new DateTimeImmutable('2011-01-20', $tz), 776 new DateTimeImmutable('2011-01-24', $tz), 777 new DateTimeImmutable('2011-01-31', $tz), 778 new DateTimeImmutable('2011-03-02', $tz), 779 new DateTimeImmutable('2011-03-07', $tz), 780 new DateTimeImmutable('2011-03-14', $tz), 781 new DateTimeImmutable('2011-03-17', $tz), 782 new DateTimeImmutable('2011-03-21', $tz), 783 new DateTimeImmutable('2011-03-22', $tz), 784 new DateTimeImmutable('2011-03-28', $tz), 785 new DateTimeImmutable('2011-05-02', $tz), 786 ], 787 $result 788 ); 789 790 } 791 792 /** 793 * @depends testValues 794 */ 795 function testMonthlyByDayByMonthDay() { 796 797 $vcal = new VCalendar(); 798 $ev = $vcal->createComponent('VEVENT'); 799 800 $ev->UID = 'bla'; 801 $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO;BYMONTHDAY=1'; 802 $dtStart = $vcal->createProperty('DTSTART'); 803 $dtStart->setDateTime(new DateTimeImmutable('2011-08-01', new DateTimeZone('UTC'))); 804 805 $ev->add($dtStart); 806 807 $vcal->add($ev); 808 809 $it = new EventIterator($vcal, (string)$ev->UID); 810 811 $max = 20; 812 $result = []; 813 foreach ($it as $item) { 814 815 $result[] = $item; 816 $max--; 817 818 if (!$max) break; 819 820 } 821 822 $tz = new DateTimeZone('UTC'); 823 824 $this->assertEquals( 825 [ 826 new DateTimeImmutable('2011-08-01', $tz), 827 new DateTimeImmutable('2012-10-01', $tz), 828 new DateTimeImmutable('2013-04-01', $tz), 829 new DateTimeImmutable('2013-07-01', $tz), 830 new DateTimeImmutable('2014-09-01', $tz), 831 new DateTimeImmutable('2014-12-01', $tz), 832 new DateTimeImmutable('2015-06-01', $tz), 833 new DateTimeImmutable('2016-02-01', $tz), 834 new DateTimeImmutable('2016-08-01', $tz), 835 new DateTimeImmutable('2017-05-01', $tz), 836 ], 837 $result 838 ); 839 840 } 841 842 /** 843 * @depends testValues 844 */ 845 function testMonthlyByDayBySetPos() { 846 847 $vcal = new VCalendar(); 848 $ev = $vcal->createComponent('VEVENT'); 849 850 $ev->UID = 'bla'; 851 $ev->RRULE = 'FREQ=MONTHLY;COUNT=10;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=1,-1'; 852 $dtStart = $vcal->createProperty('DTSTART'); 853 $dtStart->setDateTime(new DateTimeImmutable('2011-01-03', new DateTimeZone('UTC'))); 854 855 $ev->add($dtStart); 856 857 $vcal->add($ev); 858 859 $it = new EventIterator($vcal, (string)$ev->UID); 860 861 $max = 20; 862 $result = []; 863 foreach ($it as $item) { 864 865 $result[] = $item; 866 $max--; 867 868 if (!$max) break; 869 870 } 871 872 $tz = new DateTimeZone('UTC'); 873 874 $this->assertEquals( 875 [ 876 new DateTimeImmutable('2011-01-03', $tz), 877 new DateTimeImmutable('2011-01-31', $tz), 878 new DateTimeImmutable('2011-02-01', $tz), 879 new DateTimeImmutable('2011-02-28', $tz), 880 new DateTimeImmutable('2011-03-01', $tz), 881 new DateTimeImmutable('2011-03-31', $tz), 882 new DateTimeImmutable('2011-04-01', $tz), 883 new DateTimeImmutable('2011-04-29', $tz), 884 new DateTimeImmutable('2011-05-02', $tz), 885 new DateTimeImmutable('2011-05-31', $tz), 886 ], 887 $result 888 ); 889 890 } 891 892 /** 893 * @depends testValues 894 */ 895 function testYearly() { 896 897 $vcal = new VCalendar(); 898 $ev = $vcal->createComponent('VEVENT'); 899 900 $ev->UID = 'bla'; 901 $ev->RRULE = 'FREQ=YEARLY;COUNT=10;INTERVAL=3'; 902 $dtStart = $vcal->createProperty('DTSTART'); 903 $dtStart->setDateTime(new DateTimeImmutable('2011-01-01', new DateTimeZone('UTC'))); 904 905 $ev->add($dtStart); 906 907 $vcal->add($ev); 908 909 $it = new EventIterator($vcal, (string)$ev->UID); 910 911 $max = 20; 912 $result = []; 913 foreach ($it as $item) { 914 915 $result[] = $item; 916 $max--; 917 918 if (!$max) break; 919 920 } 921 922 $tz = new DateTimeZone('UTC'); 923 924 $this->assertEquals( 925 [ 926 new DateTimeImmutable('2011-01-01', $tz), 927 new DateTimeImmutable('2014-01-01', $tz), 928 new DateTimeImmutable('2017-01-01', $tz), 929 new DateTimeImmutable('2020-01-01', $tz), 930 new DateTimeImmutable('2023-01-01', $tz), 931 new DateTimeImmutable('2026-01-01', $tz), 932 new DateTimeImmutable('2029-01-01', $tz), 933 new DateTimeImmutable('2032-01-01', $tz), 934 new DateTimeImmutable('2035-01-01', $tz), 935 new DateTimeImmutable('2038-01-01', $tz), 936 ], 937 $result 938 ); 939 940 } 941 942 /** 943 * @depends testValues 944 */ 945 function testYearlyLeapYear() { 946 947 $vcal = new VCalendar(); 948 $ev = $vcal->createComponent('VEVENT'); 949 950 $ev->UID = 'bla'; 951 $ev->RRULE = 'FREQ=YEARLY;COUNT=3'; 952 $dtStart = $vcal->createProperty('DTSTART'); 953 $dtStart->setDateTime(new DateTimeImmutable('2012-02-29', new DateTimeZone('UTC'))); 954 955 $ev->add($dtStart); 956 957 $vcal->add($ev); 958 959 $it = new EventIterator($vcal, (string)$ev->UID); 960 961 $max = 20; 962 $result = []; 963 foreach ($it as $item) { 964 965 $result[] = $item; 966 $max--; 967 968 if (!$max) break; 969 970 } 971 972 $tz = new DateTimeZone('UTC'); 973 974 $this->assertEquals( 975 [ 976 new DateTimeImmutable('2012-02-29', $tz), 977 new DateTimeImmutable('2016-02-29', $tz), 978 new DateTimeImmutable('2020-02-29', $tz), 979 ], 980 $result 981 ); 982 983 } 984 985 /** 986 * @depends testValues 987 */ 988 function testYearlyByMonth() { 989 990 $vcal = new VCalendar(); 991 $ev = $vcal->createComponent('VEVENT'); 992 993 $ev->UID = 'bla'; 994 $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=4;BYMONTH=4,10'; 995 $dtStart = $vcal->createProperty('DTSTART'); 996 $dtStart->setDateTime(new DateTimeImmutable('2011-04-07', new DateTimeZone('UTC'))); 997 998 $ev->add($dtStart); 999 1000 $vcal->add($ev); 1001 1002 $it = new EventIterator($vcal, (string)$ev->UID); 1003 1004 $max = 20; 1005 $result = []; 1006 foreach ($it as $item) { 1007 1008 $result[] = $item; 1009 $max--; 1010 1011 if (!$max) break; 1012 1013 } 1014 1015 $tz = new DateTimeZone('UTC'); 1016 1017 $this->assertEquals( 1018 [ 1019 new DateTimeImmutable('2011-04-07', $tz), 1020 new DateTimeImmutable('2011-10-07', $tz), 1021 new DateTimeImmutable('2015-04-07', $tz), 1022 new DateTimeImmutable('2015-10-07', $tz), 1023 new DateTimeImmutable('2019-04-07', $tz), 1024 new DateTimeImmutable('2019-10-07', $tz), 1025 new DateTimeImmutable('2023-04-07', $tz), 1026 new DateTimeImmutable('2023-10-07', $tz), 1027 ], 1028 $result 1029 ); 1030 1031 } 1032 1033 /** 1034 * @depends testValues 1035 */ 1036 function testYearlyByMonthByDay() { 1037 1038 $vcal = new VCalendar(); 1039 $ev = $vcal->createComponent('VEVENT'); 1040 1041 $ev->UID = 'bla'; 1042 $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU'; 1043 $dtStart = $vcal->createProperty('DTSTART'); 1044 $dtStart->setDateTime(new DateTimeImmutable('2011-04-04', new DateTimeZone('UTC'))); 1045 1046 $ev->add($dtStart); 1047 1048 $vcal->add($ev); 1049 1050 $it = new EventIterator($vcal, (string)$ev->UID); 1051 1052 $max = 20; 1053 $result = []; 1054 foreach ($it as $item) { 1055 1056 $result[] = $item; 1057 $max--; 1058 1059 if (!$max) break; 1060 1061 } 1062 1063 $tz = new DateTimeZone('UTC'); 1064 1065 $this->assertEquals( 1066 [ 1067 new DateTimeImmutable('2011-04-04', $tz), 1068 new DateTimeImmutable('2011-04-24', $tz), 1069 new DateTimeImmutable('2011-10-03', $tz), 1070 new DateTimeImmutable('2011-10-30', $tz), 1071 new DateTimeImmutable('2016-04-04', $tz), 1072 new DateTimeImmutable('2016-04-24', $tz), 1073 new DateTimeImmutable('2016-10-03', $tz), 1074 new DateTimeImmutable('2016-10-30', $tz), 1075 ], 1076 $result 1077 ); 1078 1079 } 1080 1081 /** 1082 * @depends testValues 1083 */ 1084 function testFastForward() { 1085 1086 $vcal = new VCalendar(); 1087 $ev = $vcal->createComponent('VEVENT'); 1088 1089 $ev->UID = 'bla'; 1090 $ev->RRULE = 'FREQ=YEARLY;COUNT=8;INTERVAL=5;BYMONTH=4,10;BYDAY=1MO,-1SU'; 1091 $dtStart = $vcal->createProperty('DTSTART'); 1092 $dtStart->setDateTime(new DateTimeImmutable('2011-04-04', new DateTimeZone('UTC'))); 1093 1094 $ev->add($dtStart); 1095 1096 $vcal->add($ev); 1097 1098 $it = new EventIterator($vcal, (string)$ev->UID); 1099 1100 // The idea is that we're fast-forwarding too far in the future, so 1101 // there will be no results left. 1102 $it->fastForward(new DateTimeImmutable('2020-05-05', new DateTimeZone('UTC'))); 1103 1104 $max = 20; 1105 $result = []; 1106 while ($item = $it->current()) { 1107 1108 $result[] = $item; 1109 $max--; 1110 1111 if (!$max) break; 1112 $it->next(); 1113 1114 } 1115 1116 $this->assertEquals([], $result); 1117 1118 } 1119 1120 /** 1121 * @depends testValues 1122 */ 1123 function testFastForwardAllDayEventThatStopAtTheStartTime() { 1124 $vcal = new VCalendar(); 1125 $ev = $vcal->createComponent('VEVENT'); 1126 1127 $ev->UID = 'bla'; 1128 $ev->RRULE = 'FREQ=DAILY'; 1129 1130 $dtStart = $vcal->createProperty('DTSTART'); 1131 $dtStart->setDateTime(new DateTimeImmutable('2011-04-04', new DateTimeZone('UTC'))); 1132 $ev->add($dtStart); 1133 1134 $dtEnd = $vcal->createProperty('DTSTART'); 1135 $dtEnd->setDateTime(new DateTimeImmutable('2011-04-05', new DateTimeZone('UTC'))); 1136 $ev->add($dtEnd); 1137 1138 $vcal->add($ev); 1139 1140 $it = new EventIterator($vcal, (string)$ev->UID); 1141 1142 $it->fastForward(new DateTimeImmutable('2011-04-05T000000', new DateTimeZone('UTC'))); 1143 1144 $this->assertEquals(new DateTimeImmutable('2011-04-06'), $it->getDTStart()); 1145 } 1146 1147 /** 1148 * @depends testValues 1149 */ 1150 function testComplexExclusions() { 1151 1152 $vcal = new VCalendar(); 1153 $ev = $vcal->createComponent('VEVENT'); 1154 1155 $ev->UID = 'bla'; 1156 $ev->RRULE = 'FREQ=YEARLY;COUNT=10'; 1157 $dtStart = $vcal->createProperty('DTSTART'); 1158 1159 $tz = new DateTimeZone('Canada/Eastern'); 1160 $dtStart->setDateTime(new DateTimeImmutable('2011-01-01 13:50:20', $tz)); 1161 1162 $exDate1 = $vcal->createProperty('EXDATE'); 1163 $exDate1->setDateTimes([new DateTimeImmutable('2012-01-01 13:50:20', $tz), new DateTimeImmutable('2014-01-01 13:50:20', $tz)]); 1164 $exDate2 = $vcal->createProperty('EXDATE'); 1165 $exDate2->setDateTimes([new DateTimeImmutable('2016-01-01 13:50:20', $tz)]); 1166 1167 $ev->add($dtStart); 1168 $ev->add($exDate1); 1169 $ev->add($exDate2); 1170 1171 $vcal->add($ev); 1172 1173 $it = new EventIterator($vcal, (string)$ev->UID); 1174 1175 $max = 20; 1176 $result = []; 1177 foreach ($it as $item) { 1178 1179 $result[] = $item; 1180 $max--; 1181 1182 if (!$max) break; 1183 1184 } 1185 1186 $this->assertEquals( 1187 [ 1188 new DateTimeImmutable('2011-01-01 13:50:20', $tz), 1189 new DateTimeImmutable('2013-01-01 13:50:20', $tz), 1190 new DateTimeImmutable('2015-01-01 13:50:20', $tz), 1191 new DateTimeImmutable('2017-01-01 13:50:20', $tz), 1192 new DateTimeImmutable('2018-01-01 13:50:20', $tz), 1193 new DateTimeImmutable('2019-01-01 13:50:20', $tz), 1194 new DateTimeImmutable('2020-01-01 13:50:20', $tz), 1195 ], 1196 $result 1197 ); 1198 1199 } 1200 1201 /** 1202 * @depends testValues 1203 */ 1204 function testOverridenEvent() { 1205 1206 $vcal = new VCalendar(); 1207 1208 $ev1 = $vcal->createComponent('VEVENT'); 1209 $ev1->UID = 'overridden'; 1210 $ev1->RRULE = 'FREQ=DAILY;COUNT=10'; 1211 $ev1->DTSTART = '20120107T120000Z'; 1212 $ev1->SUMMARY = 'baseEvent'; 1213 1214 $vcal->add($ev1); 1215 1216 // ev2 overrides an event, and puts it on 2pm instead. 1217 $ev2 = $vcal->createComponent('VEVENT'); 1218 $ev2->UID = 'overridden'; 1219 $ev2->{'RECURRENCE-ID'} = '20120110T120000Z'; 1220 $ev2->DTSTART = '20120110T140000Z'; 1221 $ev2->SUMMARY = 'Event 2'; 1222 1223 $vcal->add($ev2); 1224 1225 // ev3 overrides an event, and puts it 2 days and 2 hours later 1226 $ev3 = $vcal->createComponent('VEVENT'); 1227 $ev3->UID = 'overridden'; 1228 $ev3->{'RECURRENCE-ID'} = '20120113T120000Z'; 1229 $ev3->DTSTART = '20120115T140000Z'; 1230 $ev3->SUMMARY = 'Event 3'; 1231 1232 $vcal->add($ev3); 1233 1234 $it = new EventIterator($vcal, 'overridden'); 1235 1236 $dates = []; 1237 $summaries = []; 1238 while ($it->valid()) { 1239 1240 $dates[] = $it->getDTStart(); 1241 $summaries[] = (string)$it->getEventObject()->SUMMARY; 1242 $it->next(); 1243 1244 } 1245 1246 $tz = new DateTimeZone('UTC'); 1247 $this->assertEquals([ 1248 new DateTimeImmutable('2012-01-07 12:00:00', $tz), 1249 new DateTimeImmutable('2012-01-08 12:00:00', $tz), 1250 new DateTimeImmutable('2012-01-09 12:00:00', $tz), 1251 new DateTimeImmutable('2012-01-10 14:00:00', $tz), 1252 new DateTimeImmutable('2012-01-11 12:00:00', $tz), 1253 new DateTimeImmutable('2012-01-12 12:00:00', $tz), 1254 new DateTimeImmutable('2012-01-14 12:00:00', $tz), 1255 new DateTimeImmutable('2012-01-15 12:00:00', $tz), 1256 new DateTimeImmutable('2012-01-15 14:00:00', $tz), 1257 new DateTimeImmutable('2012-01-16 12:00:00', $tz), 1258 ], $dates); 1259 1260 $this->assertEquals([ 1261 'baseEvent', 1262 'baseEvent', 1263 'baseEvent', 1264 'Event 2', 1265 'baseEvent', 1266 'baseEvent', 1267 'baseEvent', 1268 'baseEvent', 1269 'Event 3', 1270 'baseEvent', 1271 ], $summaries); 1272 1273 } 1274 1275 /** 1276 * @depends testValues 1277 */ 1278 function testOverridenEvent2() { 1279 1280 $vcal = new VCalendar(); 1281 1282 $ev1 = $vcal->createComponent('VEVENT'); 1283 $ev1->UID = 'overridden'; 1284 $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3'; 1285 $ev1->DTSTART = '20120112T120000Z'; 1286 $ev1->SUMMARY = 'baseEvent'; 1287 1288 $vcal->add($ev1); 1289 1290 // ev2 overrides an event, and puts it 6 days earlier instead. 1291 $ev2 = $vcal->createComponent('VEVENT'); 1292 $ev2->UID = 'overridden'; 1293 $ev2->{'RECURRENCE-ID'} = '20120119T120000Z'; 1294 $ev2->DTSTART = '20120113T120000Z'; 1295 $ev2->SUMMARY = 'Override!'; 1296 1297 $vcal->add($ev2); 1298 1299 $it = new EventIterator($vcal, 'overridden'); 1300 1301 $dates = []; 1302 $summaries = []; 1303 while ($it->valid()) { 1304 1305 $dates[] = $it->getDTStart(); 1306 $summaries[] = (string)$it->getEventObject()->SUMMARY; 1307 $it->next(); 1308 1309 } 1310 1311 $tz = new DateTimeZone('UTC'); 1312 $this->assertEquals([ 1313 new DateTimeImmutable('2012-01-12 12:00:00', $tz), 1314 new DateTimeImmutable('2012-01-13 12:00:00', $tz), 1315 new DateTimeImmutable('2012-01-26 12:00:00', $tz), 1316 1317 ], $dates); 1318 1319 $this->assertEquals([ 1320 'baseEvent', 1321 'Override!', 1322 'baseEvent', 1323 ], $summaries); 1324 1325 } 1326 1327 /** 1328 * @depends testValues 1329 */ 1330 function testOverridenEventNoValuesExpected() { 1331 1332 $vcal = new VCalendar(); 1333 $ev1 = $vcal->createComponent('VEVENT'); 1334 1335 $ev1->UID = 'overridden'; 1336 $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3'; 1337 $ev1->DTSTART = '20120124T120000Z'; 1338 $ev1->SUMMARY = 'baseEvent'; 1339 1340 $vcal->add($ev1); 1341 1342 // ev2 overrides an event, and puts it 6 days earlier instead. 1343 $ev2 = $vcal->createComponent('VEVENT'); 1344 $ev2->UID = 'overridden'; 1345 $ev2->{'RECURRENCE-ID'} = '20120131T120000Z'; 1346 $ev2->DTSTART = '20120125T120000Z'; 1347 $ev2->SUMMARY = 'Override!'; 1348 1349 $vcal->add($ev2); 1350 1351 $it = new EventIterator($vcal, 'overridden'); 1352 1353 $dates = []; 1354 $summaries = []; 1355 1356 // The reported problem was specifically related to the VCALENDAR 1357 // expansion. In this parcitular case, we had to forward to the 28th of 1358 // january. 1359 $it->fastForward(new DateTimeImmutable('2012-01-28 23:00:00')); 1360 1361 // We stop the loop when it hits the 6th of februari. Normally this 1362 // iterator would hit 24, 25 (overriden from 31) and 7 feb but because 1363 // we 'filter' from the 28th till the 6th, we should get 0 results. 1364 while ($it->valid() && $it->getDTStart() < new DateTimeImmutable('2012-02-06 23:00:00')) { 1365 1366 $dates[] = $it->getDTStart(); 1367 $summaries[] = (string)$it->getEventObject()->SUMMARY; 1368 $it->next(); 1369 1370 } 1371 1372 $this->assertEquals([], $dates); 1373 $this->assertEquals([], $summaries); 1374 1375 } 1376 1377 /** 1378 * @depends testValues 1379 */ 1380 function testRDATE() { 1381 1382 $vcal = new VCalendar(); 1383 $ev = $vcal->createComponent('VEVENT'); 1384 1385 $ev->UID = 'bla'; 1386 $ev->RDATE = [ 1387 new DateTimeImmutable('2014-08-07', new DateTimeZone('UTC')), 1388 new DateTimeImmutable('2014-08-08', new DateTimeZone('UTC')), 1389 ]; 1390 $dtStart = $vcal->createProperty('DTSTART'); 1391 $dtStart->setDateTime(new DateTimeImmutable('2011-10-07', new DateTimeZone('UTC'))); 1392 1393 $ev->add($dtStart); 1394 1395 $vcal->add($ev); 1396 1397 $it = new EventIterator($vcal, $ev->UID); 1398 1399 // Max is to prevent overflow 1400 $max = 12; 1401 $result = []; 1402 foreach ($it as $item) { 1403 1404 $result[] = $item; 1405 $max--; 1406 1407 if (!$max) break; 1408 1409 } 1410 1411 $tz = new DateTimeZone('UTC'); 1412 1413 $this->assertEquals( 1414 [ 1415 new DateTimeImmutable('2011-10-07', $tz), 1416 new DateTimeImmutable('2014-08-07', $tz), 1417 new DateTimeImmutable('2014-08-08', $tz), 1418 ], 1419 $result 1420 ); 1421 1422 } 1423 1424 /** 1425 * @depends testValues 1426 * @expectedException \InvalidArgumentException 1427 */ 1428 function testNoMasterBadUID() { 1429 1430 $vcal = new VCalendar(); 1431 // ev2 overrides an event, and puts it on 2pm instead. 1432 $ev2 = $vcal->createComponent('VEVENT'); 1433 $ev2->UID = 'overridden'; 1434 $ev2->{'RECURRENCE-ID'} = '20120110T120000Z'; 1435 $ev2->DTSTART = '20120110T140000Z'; 1436 $ev2->SUMMARY = 'Event 2'; 1437 1438 $vcal->add($ev2); 1439 1440 // ev3 overrides an event, and puts it 2 days and 2 hours later 1441 $ev3 = $vcal->createComponent('VEVENT'); 1442 $ev3->UID = 'overridden'; 1443 $ev3->{'RECURRENCE-ID'} = '20120113T120000Z'; 1444 $ev3->DTSTART = '20120115T140000Z'; 1445 $ev3->SUMMARY = 'Event 3'; 1446 1447 $vcal->add($ev3); 1448 1449 $it = new EventIterator($vcal, 'broken'); 1450 1451 } 1452} 1453