1
0
mirror of https://github.com/rlanvin/php-rrule.git synced 2024-11-28 05:24:10 +01:00

Add $limit to getOccurrences and getOccurencesBetween

This commit is contained in:
rlanvin 2017-05-06 12:58:42 +01:00
parent 031b5e78f1
commit 7437503a73
6 changed files with 135 additions and 24 deletions

View File

@ -7,6 +7,7 @@
- Add `explicit_infinite` and `include_start` options to `humanReadable` to respectivity omit "forever" and the start date from the sentence.
- RSet constructor now accepts a string to build a RSET from a RFC string [#26](https://github.com/rlanvin/php-rrule/issues/26)
- New factory method `RRule::createFromRfcString()` to build either a RRule or a RSet from a string
- Add a `$limit` parameter to `getOccurrences()` and `getOccurrencesBetween()` to make working with infinite rule easier
### Fixed

View File

@ -731,26 +731,29 @@ class RRule implements RRuleInterface
/**
* Return all the occurrences in an array of \DateTime.
*
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrences()
public function getOccurrences($limit = null)
{
if ( $this->isInfinite() ) {
if ( ! $limit && $this->isInfinite() ) {
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
}
// cached version already computed
$iterator = $this;
if ( $this->total !== null ) {
$res = array();
foreach ( $this->cache as $occurrence ) {
$res[] = clone $occurrence; // we have to clone because DateTime is not immutable
}
return $res;
$iterator = $this->cache;
}
$res = array();
foreach ( $this as $occurrence ) {
$res[] = $occurrence;
$n = 0;
foreach ( $iterator as $occurrence ) {
$res[] = clone $occurrence; // we have to clone because DateTime is not immutable
$n += 1;
if ( $limit && $n >= $limit ) {
break;
}
}
return $res;
}
@ -760,9 +763,10 @@ class RRule implements RRuleInterface
*
* @param mixed $begin Can be null to return all occurrences before $end
* @param mixed $end Can be null to return all occurrences after $begin
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrencesBetween($begin, $end)
public function getOccurrencesBetween($begin, $end, $limit = null)
{
if ( $begin !== null ) {
$begin = self::parseDate($begin);
@ -771,7 +775,7 @@ class RRule implements RRuleInterface
if ( $end !== null ) {
$end = self::parseDate($end);
}
elseif ( $this->isInfinite() ) {
elseif ( ! $limit && $this->isInfinite() ) {
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
}
@ -781,6 +785,7 @@ class RRule implements RRuleInterface
}
$res = array();
$n = 0;
foreach ( $iterator as $occurrence ) {
if ( $begin !== null && $occurrence < $begin ) {
continue;
@ -789,6 +794,10 @@ class RRule implements RRuleInterface
break;
}
$res[] = clone $occurrence;
$n += 1;
if ( $limit && $n >= $limit ) {
break;
}
}
return $res;
}

View File

@ -19,18 +19,20 @@ interface RRuleInterface extends \Iterator, \ArrayAccess, \Countable
/**
* Return all the occurrences in an array of \DateTime.
*
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrences();
public function getOccurrences($limit = null);
/**
* Return all the ocurrences after a date, before a date, or between two dates.
*
* @param mixed $begin Can be null to return all occurrences before $end
* @param mixed $end Can be null to return all occurrences after $begin
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrencesBetween($begin, $end);
public function getOccurrencesBetween($begin, $end, $limit = null);
/**
* Return true if $date is an occurrence.

View File

@ -321,26 +321,29 @@ class RSet implements RRuleInterface
/**
* Return all the occurrences in an array of \DateTime.
*
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrences()
public function getOccurrences($limit = null)
{
if ( $this->isInfinite() ) {
if ( !$limit && $this->isInfinite() ) {
throw new \LogicException('Cannot get all occurrences of an infinite recurrence set.');
}
// cached version already computed
$iterator = $this;
if ( $this->total !== null ) {
$res = array();
foreach ( $this->cache as $occurrence ) {
$res[] = clone $occurrence; // we have to clone because DateTime is not immutable
}
return $res;
$iterator = $this->cache;
}
$res = array();
foreach ( $this as $occurrence ) {
$res[] = $occurrence;
$n = 0;
foreach ( $iterator as $occurrence ) {
$res[] = clone $occurrence; // we have to clone because DateTime is not immutable
$n += 1;
if ( $limit && $n >= $limit ) {
break;
}
}
return $res;
}
@ -350,9 +353,10 @@ class RSet implements RRuleInterface
*
* @param mixed $begin Can be null to return all occurrences before $end
* @param mixed $end Can be null to return all occurrences after $begin
* @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
* @return array An array of \DateTime objects
*/
public function getOccurrencesBetween($begin, $end)
public function getOccurrencesBetween($begin, $end, $limit = null)
{
if ( $begin !== null ) {
$begin = RRule::parseDate($begin);
@ -361,7 +365,7 @@ class RSet implements RRuleInterface
if ( $end !== null ) {
$end = RRule::parseDate($end);
}
elseif ( $this->isInfinite() ) {
elseif ( ! $limit && $this->isInfinite() ) {
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
}
@ -371,6 +375,7 @@ class RSet implements RRuleInterface
}
$res = array();
$n = 0;
foreach ( $iterator as $occurrence ) {
if ( $begin !== null && $occurrence < $begin ) {
continue;
@ -379,6 +384,10 @@ class RSet implements RRuleInterface
break;
}
$res[] = clone $occurrence;
$n += 1;
if ( $limit && $n >= $limit ) {
break;
}
}
return $res;
}

View File

@ -1715,6 +1715,50 @@ class RRuleTest extends PHPUnit_Framework_TestCase
}
}
///////////////////////////////////////////////////////////////////////////////
// GetOccurrences
public function testGetOccurrences()
{
$rrule = new RRule(array(
'FREQ' => 'DAILY',
'DTSTART' => '2017-01-01'
));
$this->assertCount(1, $rrule->getOccurrences(1));
$this->assertEquals([date_create('2017-01-01')], $rrule->getOccurrences(1));
$this->assertCount(5, $rrule->getOccurrences(5));
$this->assertEquals([
date_create('2017-01-01'),date_create('2017-01-02'),date_create('2017-01-03'),
date_create('2017-01-04'),date_create('2017-01-05')
], $rrule->getOccurrences(5));
try {
$rrule->getOccurrences();
$this->fail('Expected exception (infinite rule) not thrown');
} catch ( \LogicException $e ) {
}
}
public function testGetOccurrencesBetween()
{
$rrule = new RRule(array(
'FREQ' => 'DAILY',
'DTSTART' => '2017-01-01'
));
$this->assertCount(1, $rrule->getOccurrencesBetween('2017-01-01', null, 1));
$this->assertCount(1, $rrule->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
$this->assertEquals([date_create('2017-02-01')], $rrule->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
$this->assertCount(5, $rrule->getOccurrencesBetween('2017-01-01', null, 5));
try {
$rrule->getOccurrencesBetween('2017-01-01', null);
$this->fail('Expected exception (infinite rule) not thrown');
} catch ( \LogicException $e ) {
}
}
///////////////////////////////////////////////////////////////////////////////
// RFC Strings

View File

@ -427,6 +427,52 @@ class RSetTest extends PHPUnit_Framework_TestCase
$this->assertCount(0, $rset->getExDates());
}
///////////////////////////////////////////////////////////////////////////////
// GetOccurrences
public function testGetOccurrences()
{
$rset = new RSet();
$rset->addRRule(new RRule(array(
'FREQ' => 'DAILY',
'DTSTART' => '2017-01-01'
)));
$this->assertCount(1, $rset->getOccurrences(1));
$this->assertEquals([date_create('2017-01-01')], $rset->getOccurrences(1));
$this->assertCount(5, $rset->getOccurrences(5));
$this->assertEquals([
date_create('2017-01-01'),date_create('2017-01-02'),date_create('2017-01-03'),
date_create('2017-01-04'),date_create('2017-01-05')
], $rset->getOccurrences(5));
try {
$rset->getOccurrences();
$this->fail('Expected exception (infinite rule) not thrown');
} catch ( \LogicException $e ) {
}
}
public function testGetOccurrencesBetween()
{
$rset = new RSet();
$rset->addRRule(new RRule(array(
'FREQ' => 'DAILY',
'DTSTART' => '2017-01-01'
)));
$this->assertCount(1, $rset->getOccurrencesBetween('2017-01-01', null, 1));
$this->assertCount(1, $rset->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
$this->assertEquals([date_create('2017-02-01')], $rset->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
$this->assertCount(5, $rset->getOccurrencesBetween('2017-01-01', null, 5));
try {
$rset->getOccurrencesBetween('2017-01-01', null);
$this->fail('Expected exception (infinite rule) not thrown');
} catch ( \LogicException $e ) {
}
}
///////////////////////////////////////////////////////////////////////////////
// RFC Strings