From 8eaabc00c6b43259d5d8639355260a809f9c1c16 Mon Sep 17 00:00:00 2001 From: Kay Lukas Date: Fri, 7 Dec 2018 18:47:51 +0100 Subject: [PATCH] Add testcases --- lib/Recur/RRuleIterator.php | 33 +- tests/VObject/Recur/FastForwardTest.php | 431 ++++++++++++++++++++++ tests/VObject/Recur/RRuleIteratorTest.php | 1 - 3 files changed, 448 insertions(+), 17 deletions(-) create mode 100644 tests/VObject/Recur/FastForwardTest.php diff --git a/lib/Recur/RRuleIterator.php b/lib/Recur/RRuleIterator.php index c1992890f..1e10183e7 100644 --- a/lib/Recur/RRuleIterator.php +++ b/lib/Recur/RRuleIterator.php @@ -2,7 +2,6 @@ namespace Sabre\VObject\Recur; -use DateTimeImmutable; use DateTimeInterface; use Iterator; use Sabre\VObject\DateTimeParser; @@ -85,6 +84,7 @@ public function rewind() /** * Goes on to the next iteration. + * * @param int $amount */ public function next($amount = 1) @@ -92,19 +92,19 @@ public function next($amount = 1) // Otherwise, we find the next event in the normal RRULE // sequence. switch ($this->frequency) { - case 'hourly' : + case 'hourly': $this->nextHourly($amount); break; - case 'daily' : + case 'daily': $this->nextDaily($amount); break; - case 'weekly' : + case 'weekly': $this->nextWeekly($amount); break; - case 'monthly' : + case 'monthly': $this->nextMonthly($amount); break; - case 'yearly' : + case 'yearly': $this->nextYearly($amount); break; } @@ -135,19 +135,19 @@ public function fastForward(DateTimeInterface $dt) do { $diff = $this->currentDate->diff($dt); switch ($this->frequency) { - case 'hourly' : + case 'hourly': $i = $diff->days * 24; break; - case 'daily' : + case 'daily': $i = $diff->days; break; - case 'weekly' : + case 'weekly': $i = $diff->days / 7; break; - case 'monthly' : + case 'monthly': $i = $diff->days / 30; break; - case 'yearly' : + case 'yearly': $i = $diff->days / 365; break; } @@ -355,6 +355,7 @@ protected function nextDaily($amount = 1) { if (!$this->byHour && !$this->byDay) { $this->currentDate = $this->currentDate->modify('+'.$amount * $this->interval.' days'); + return; } @@ -384,7 +385,6 @@ protected function nextDaily($amount = 1) $amount = 1; } - // Current month of the year $currentMonth = $this->currentDate->format('n'); @@ -403,10 +403,11 @@ protected function nextDaily($amount = 1) /** * Does the processing for advancing the iterator for weekly frequency. */ - protected function nextWeekly($amount = 1) { - + protected function nextWeekly($amount = 1) + { if (!$this->byHour && !$this->byDay) { - $this->currentDate = $this->currentDate->modify('+' .($amount * $this->interval).' weeks'); + $this->currentDate = $this->currentDate->modify('+'.($amount * $this->interval).' weeks'); + return; } @@ -435,7 +436,7 @@ protected function nextWeekly($amount = 1) { $currentHour = (int) $this->currentDate->format('G'); // We need to roll over to the next week - if ($currentDay === $firstDay && (!$this->byHour || $currentHour == '0')) { + if ($currentDay === $firstDay && (!$this->byHour || '0' == $currentHour)) { $this->currentDate = $this->currentDate->modify('+'.(($amount * $this->interval) - 1).' weeks'); $amount = 1; // We need to go to the first day of this week, but only if we diff --git a/tests/VObject/Recur/FastForwardTest.php b/tests/VObject/Recur/FastForwardTest.php new file mode 100644 index 000000000..df9120561 --- /dev/null +++ b/tests/VObject/Recur/FastForwardTest.php @@ -0,0 +1,431 @@ +fastForward($ffDate); + $ru = getrusage(); + $endTime = $ru['ru_utime.tv_sec'] * 1000000 + $ru['ru_utime.tv_usec']; + $this->assertLessThan(self::FF_TIMEOUT, $endTime - $startTime); + } + + public function testFastForwardYearlyBasic() + { + $startDate = new DateTime('1970-10-23 00:00:00', new DateTimeZone('zulu')); + $ffDate = new DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(99999, 1, 1); + $rrule = new RRuleIterator('FREQ=YEARLY', $startDate); + + $this->fastForward($rrule, $ffDate); + + $year = 60 * 60 * 24 * 365; + $expected = (new DateTime()) + ->setTimezone(new DateTimeZone('zulu')) + ->setDate(99999, 10, 23) + ->setTime(0, 0, 0) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // It's a leap + $expected += $year + 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // leap + $expected += $year + 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $year; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // leap + $expected += $year + 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + } + + public function testFastForwardYearlyByYearDay() + { + $startDate = new \DateTime('1970-10-23 00:00:00', new \DateTimeZone('zulu')); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(99998, 12, 31); + $rrule = new RRuleIterator('FREQ=YEARLY;BYYEARDAY=1,20,300', $startDate); + + $this->fastForward($rrule, $ffDate); + + $day = 60 * 60 * 24; + $expected = (new DateTime()) + ->setTimezone(new DateTimeZone('zulu')) + ->setDate(99999, 1, 1)// 20th day + ->setTime(0, 0, 0) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // 300th day + $expected += 19 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // 1st day + $expected += 280 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // 20th day + $expected += 66 * $day; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // 300th day + $rrule->next(); + $expected += 19 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += 280 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + // 1st day (leap year, we have 366 days in this year) + $expected += 67 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += 19 * $day; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardYearlyByWeekNo() + { + $startDate = new \DateTime('1970-10-23 00:00:00', new \DateTimeZone('zulu')); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(99999, 1, 1); + $rrule = new RRuleIterator('FREQ=YEARLY;BYWEEKNO=1,20', $startDate); + + $this->fastForward($rrule, $ffDate); + + $day = 60 * 60 * 24; + $week = 7 * $day; + $expected = (new DateTime()) + ->setTimezone(new DateTimeZone('zulu')) + ->setDate(99999, 1, 4)// 1st day + ->setTime(0, 0, 0) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + $rrule->next(); + $expected += $week * 19; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardYearlyAdvanced() + { + $startDate = new \DateTime('1970-10-23 12:34:56', new \DateTimeZone('zulu')); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(9999, 1, 20)->setTime(0, 0, 13); + $rrule = new RRuleIterator('FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30', $startDate); + + $this->fastForward($rrule, $ffDate); + + $expected = (new DateTime('midnight', new DateTimeZone('zulu'))) + ->setDate(10000, 1, 2) + ->setTime(8, 30, 56) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 7 * 24 * 60 * 60 - 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 7 * 24 * 60 * 60 - 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 7 * 24 * 60 * 60 - 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 7 * 24 * 60 * 60 - 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // jump to 6th january 10002 + $rrule->next(); + $expected = (new DateTime('midnight', new DateTimeZone('zulu'))) + ->setDate(10002, 1, 6) + ->setTime(8, 30, 56) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $rrule->next(); + $expected += 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardMonthlyBasic() + { + $startDate = new \DateTime('1970-10-23 22:42:31', new \DateTimeZone('zulu')); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(18000, 1, 1); + $rrule = new RRuleIterator('FREQ=MONTHLY', $startDate); + + $this->fastForward($rrule, $ffDate); + + $expected = (new DateTime('midnight', new DateTimeZone('zulu'))) + ->setDate(18000, 1, 23) + ->setTime(22, 42, 31) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // february + $rrule->next(); + $expected += 31 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // march + $rrule->next(); + $expected += 29 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // april + $rrule->next(); + $expected += 31 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // may + $rrule->next(); + $expected += 30 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // june + $rrule->next(); + $expected += 31 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // july + $rrule->next(); + $expected += 30 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + // august + $rrule->next(); + $expected += 31 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardMonthly31thDay() + { + $timezone = 'America/New_York'; + $startDate = new \DateTime('1970-01-31 00:00:00', new \DateTimeZone($timezone)); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(18000, 1, 1); + $rrule = new RRuleIterator('FREQ=MONTHLY', $startDate); + + $this->fastForward($rrule, $ffDate); + + $expected = (new DateTime('midnight', new DateTimeZone('America/New_York'))) + ->setDate(18000, 1, 31) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // march + $rrule->next(); + $expected += (29 + 31) * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // may + $rrule->next(); + $expected += (30 + 31) * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // july + $rrule->next(); + $expected += (30 + 31) * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // august + $rrule->next(); + $expected += 31 * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // october + $rrule->next(); + $expected += (30 + 31) * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // december + $rrule->next(); + $expected += (30 + 31) * 24 * 60 * 60; + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardMonthlyAdvanced() + { + $timezone = 'America/New_York'; + $startDate = new \DateTime('1970-01-31 00:00:00', new DateTimeZone($timezone)); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(8000, 1, 1); + $rrule = new RRuleIterator('FREQ=MONTHLY;INTERVAL=2;BYDAY=1MO,2TU,3WE,4TH', $startDate); + + $this->fastForward($rrule, $ffDate); + + // monday + $expected = (new DateTime('midnight', new DateTimeZone($timezone))) + ->setDate(8000, 1, 3) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // tuesday + $expected += 8 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // wednesday + $expected += 8 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // thursday + $expected += 8 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // monday march + $expected += (29 + 10) * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // tuesday + $expected += 8 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // wednesday (this month starts on wednesday so that's just the next day) + $expected += 1 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // thursday + $expected += 8 * 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardDailyBasic() + { + $timezone = 'America/New_York'; + $startDate = new \DateTime('1970-10-23 00:00:00', new \DateTimeZone($timezone)); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(4000, 1, 1); + $rrule = new RRuleIterator('FREQ=DAILY', $startDate); + + $this->fastForward($rrule, $ffDate); + + $expected = (new DateTime('midnight', new DateTimeZone($timezone))) + ->setDate(4000, 1, 1) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + $expected += 24 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } + + public function testFastForwardDailyAdvanced() + { + $timezone = 'America/New_York'; + $startDate = new \DateTime('1970-10-23 00:00:00', new \DateTimeZone($timezone)); + $ffDate = new \DateTime('midnight', new DateTimeZone('zulu')); + $ffDate->setDate(4000, 1, 1); + $rrule = new RRuleIterator('FREQ=DAILY;BYHOUR=16,17,18;INTERVAL=10', $startDate); + + $this->fastForward($rrule, $ffDate); + + $expected = (new DateTime('midnight', new DateTimeZone($timezone))) + ->setDate(4000, 1, 4) + ->setTime(16, 0, 0) + ->getTimestamp(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 17:00 + $expected += 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 18:00 + $expected += 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 16:00 + $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 17:00 + $expected += 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 18:00 + $expected += 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + + // 16:00 + $expected += 10 * 24 * 60 * 60 - 2 * 60 * 60; + $rrule->next(); + $this->assertEquals($expected, $rrule->current()->getTimestamp()); + } +} diff --git a/tests/VObject/Recur/RRuleIteratorTest.php b/tests/VObject/Recur/RRuleIteratorTest.php index fa4e75031..6e7d47dd7 100644 --- a/tests/VObject/Recur/RRuleIteratorTest.php +++ b/tests/VObject/Recur/RRuleIteratorTest.php @@ -488,7 +488,6 @@ public function testYearlyByMonthByDay() ); } - public function testYearlyNewYearsEve() { $this->parse(