1
0
mirror of https://github.com/rlanvin/php-rrule.git synced 2025-02-20 09:54:16 +01:00

Fix cache related bug at weekly frequencies

This commit is contained in:
rlanvin 2016-03-24 09:22:32 +02:00
parent 3162337ace
commit 3a84bcc6be
3 changed files with 103 additions and 13 deletions

View File

@ -11,7 +11,9 @@
### Fixed
- Fix bug preventing the iteration of multiple instances of RRule at the same time
- Fix various bugs causing corruption of the cache in some circumstances (related to DateTime object being mutable)
- Fix occursAt failing when the date passed was a different timezone [#8](https://github.com/rlanvin/php-rrule/pull/8)
- Fix bug at WEEKLY frequency with a partially filled cache in some circumstances
- Fix various reference bugs causing corruption of the cache in some circumstances (related to DateTime object being mutable)
### Removed

View File

@ -732,7 +732,9 @@ class RRule implements RRuleInterface
*/
public function occursAt($date)
{
$date = self::parseDate($date)->setTimezone($this->dtstart->getTimezone());
$date = self::parseDate($date);
// convert timezone to dtstart timezone for comparison
$date->setTimezone($this->dtstart->getTimezone());
if ( in_array($date, $this->cache) ) {
// in the cache (whether cache is complete or not)
@ -1441,7 +1443,7 @@ class RRule implements RRuleInterface
// calculation magic at the end of the loop (when incrementing)
// to realign on first pass.
$tmp = clone $dtstart;
$tmp->modify('-'.pymod($this->dtstart->format('N') - $this->wkst,7).'days');
$tmp->modify('-'.pymod($dtstart->format('N') - $this->wkst,7).'days');
list($year,$month,$day,$hour,$minute,$second) = explode(' ',$tmp->format('Y n j G i s'));
unset($tmp);
}

View File

@ -2,6 +2,10 @@
use RRule\RRule;
// make sure that the tests are run in the same timezone everywhere
// Europe/Helsinki has DST
date_default_timezone_set('Europe/Helsinki');
class RRuleTest extends PHPUnit_Framework_TestCase
{
/**
@ -258,8 +262,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'DTSTART' => '1997-09-02'
), $rule));
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -324,8 +337,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'DTSTART' => '1997-09-02'
), $rule));
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -391,8 +413,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'DTSTART' => '1997-09-02'
), $rule));
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -507,8 +538,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'DTSTART' => '1997-09-02 09:00:00'
), $rule));
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -623,8 +663,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'DTSTART' => '1997-09-02 09:00:00'
), $rule));
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -747,6 +796,10 @@ class RRuleTest extends PHPUnit_Framework_TestCase
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
/**
@ -1340,8 +1393,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
{
$rule = new RRule($rule);
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), 'RRule occurs at: '.$date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -1548,8 +1610,17 @@ class RRuleTest extends PHPUnit_Framework_TestCase
{
$rule = new RRule($rule);
$this->assertEquals($occurrences, $rule->getOccurrences());
$this->assertEquals($occurrences, $rule->getOccurrences(), 'Cached version');
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), 'RRule occurs at: '.$date->format('r'));
$this->assertTrue($rule->occursAt($date), $date->format('r').' in cached version');
}
$rule->clearCache();
foreach ( $occurrences as $date ) {
$this->assertTrue($rule->occursAt($date), $date->format('r').' in uncached version');
}
$rule->clearCache();
for ( $i = 0; $i < count($occurrences); $i++ ) {
$this->assertEquals($rule[$i], $occurrences[$i], 'array access uncached');
}
}
@ -1709,10 +1780,21 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'dtstart' => date_create('2015-07-01 09:00:00', new DateTimeZone('Australia/Sydney'))
));
$this->assertTrue($rrule->occursAt(date_create('2015-07-02 09:00:00',new DateTimeZone('Australia/Sydney'))));
$this->assertTrue($rrule->occursAt(date_create('2015-07-01 23:00:00',new DateTimeZone('UTC'))), 'Timezone is converted');
$this->assertTrue($rrule->occursAt(date_create('2015-07-01 23:00:00',new DateTimeZone('UTC'))), 'Timezone is converted for comparison (cached)');
$rrule->clearCache();
$this->assertTrue($rrule->occursAt(date_create('2015-07-01 23:00:00',new DateTimeZone('UTC'))), 'Timezone is converted for comparison (uncached)');
$rrule->clearCache();
$this->assertFalse($rrule->occursAt('2015-07-02 09:00:00'), 'When passed a string, default timezone is used for creating the DateTime');
$rrule->clearCache();
$this->assertTrue($rrule->occursAt('Wed, 01 Jul 2015 09:00:00 +1000'), 'When passed a string with timezone, timezone is kept (uncached)');
$this->assertTrue($rrule->occursAt('Wed, 01 Jul 2015 09:00:00 +1000'), 'When passed a string with timezone, timezone is kept (cached)');
$rrule->clearCache();
$this->assertTrue($rrule->occursAt('2015-07-01T09:00:00+10:00'), 'When passed a string with timezone, timezone is kept (uncached)');
$this->assertTrue($rrule->occursAt('2015-07-01T09:00:00+10:00'), 'When passed a string with timezone, timezone is kept (cached)');
// test with DST
$rrule = new RRule(array(
'freq' => 'daily',
@ -1720,10 +1802,14 @@ class RRuleTest extends PHPUnit_Framework_TestCase
'dtstart' => date_create('2015-07-01 09:00:00', new DateTimeZone('Europe/Helsinki'))
));
$this->assertTrue($rrule->occursAt(date_create('2015-07-02 09:00:00',new DateTimeZone('Europe/Helsinki'))));
$this->assertTrue($rrule->occursAt(date_create('2015-07-02 06:00:00',new DateTimeZone('UTC'))), 'During summer time, Europe/Helsinki is UTC+3');
$this->assertTrue($rrule->occursAt(date_create('2015-07-02 06:00:00',new DateTimeZone('UTC'))), 'During summer time, Europe/Helsinki is UTC+3 (cached)');
$rrule->clearCache();
$this->assertTrue($rrule->occursAt(date_create('2015-07-02 06:00:00',new DateTimeZone('UTC'))), 'During summer time, Europe/Helsinki is UTC+3 (uncached)');
$this->assertTrue($rrule->occursAt(date_create('2015-12-02 09:00:00',new DateTimeZone('Europe/Helsinki'))));
$this->assertTrue($rrule->occursAt(date_create('2015-12-02 07:00:00',new DateTimeZone('UTC'))), 'During winter time, Europe/Helsinki is UTC+2');
$this->assertTrue($rrule->occursAt(date_create('2015-12-02 07:00:00',new DateTimeZone('UTC'))), 'During winter time, Europe/Helsinki is UTC+2 (cached)');
$rrule->clearCache();
$this->assertTrue($rrule->occursAt(date_create('2015-12-02 07:00:00',new DateTimeZone('UTC'))), 'During winter time, Europe/Helsinki is UTC+2 (uncached)');
}
public function testIsFinite()