mirror of
https://github.com/rlanvin/php-rrule.git
synced 2025-04-12 02:02:27 +02:00
parent
200b923c9e
commit
3d72c9efaf
@ -7,6 +7,12 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- New option `custom_path` to `humanReadable()` to use custom translation files [#56](https://github.com/rlanvin/php-rrule/issues/56)
|
- New option `custom_path` to `humanReadable()` to use custom translation files [#56](https://github.com/rlanvin/php-rrule/issues/56)
|
||||||
|
- New helpers methods [#60](https://github.com/rlanvin/php-rrule/issues/60)
|
||||||
|
- `getOccurrencesBefore`
|
||||||
|
- `getOccurrencesAfter`
|
||||||
|
- `getNthOccurrencesBefore`
|
||||||
|
- `getNthOccurrencesAfter`
|
||||||
|
- `getNthOccurrencesFrom`
|
||||||
|
|
||||||
## [1.6.3] - 2019-01-13
|
## [1.6.3] - 2019-01-13
|
||||||
|
|
||||||
|
15
README.md
15
README.md
@ -41,27 +41,12 @@ The recommended way is to install the lib [through Composer](http://getcomposer.
|
|||||||
|
|
||||||
Simply run `composer require rlanvin/php-rrule` for it to be automatically installed and included in your `composer.json`.
|
Simply run `composer require rlanvin/php-rrule` for it to be automatically installed and included in your `composer.json`.
|
||||||
|
|
||||||
Alternatively, just add this to your `composer.json` file and then run `composer install` (you can replace `2.*` by any version selector, or even `dev-master` for the latest development version).
|
|
||||||
|
|
||||||
```JSON
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"rlanvin/php-rrule": "2.*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can use the autoloader, and you will have access to the library:
|
Now you can use the autoloader, and you will have access to the library:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
require 'vendor/autoload.php';
|
require 'vendor/autoload.php';
|
||||||
```
|
```
|
||||||
|
|
||||||
### Alternative method (not recommended)
|
|
||||||
|
|
||||||
- Download [the latest release](https://github.com/rlanvin/php-rrule/releases/latest)
|
|
||||||
- Put the files in a folder that is autoloaded, or `include` or `require` them
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Complete documentation is available in [the wiki](https://github.com/rlanvin/php-rrule/wiki).
|
Complete documentation is available in [the wiki](https://github.com/rlanvin/php-rrule/wiki).
|
||||||
|
108
src/RRule.php
108
src/RRule.php
@ -91,6 +91,8 @@ function is_leap_year($year)
|
|||||||
*/
|
*/
|
||||||
class RRule implements RRuleInterface
|
class RRule implements RRuleInterface
|
||||||
{
|
{
|
||||||
|
use RRuleTrait;
|
||||||
|
|
||||||
const SECONDLY = 7;
|
const SECONDLY = 7;
|
||||||
const MINUTELY = 6;
|
const MINUTELY = 6;
|
||||||
const HOURLY = 5;
|
const HOURLY = 5;
|
||||||
@ -734,80 +736,6 @@ class RRule implements RRuleInterface
|
|||||||
return ! $this->count && ! $this->until;
|
return ! $this->count && ! $this->until;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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($limit = null)
|
|
||||||
{
|
|
||||||
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 ) {
|
|
||||||
$iterator = $this->cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = array();
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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, $limit = null)
|
|
||||||
{
|
|
||||||
if ( $begin !== null ) {
|
|
||||||
$begin = self::parseDate($begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $end !== null ) {
|
|
||||||
$end = self::parseDate($end);
|
|
||||||
}
|
|
||||||
elseif ( ! $limit && $this->isInfinite() ) {
|
|
||||||
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$iterator = $this;
|
|
||||||
if ( $this->total !== null ) {
|
|
||||||
$iterator = $this->cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = array();
|
|
||||||
$n = 0;
|
|
||||||
foreach ( $iterator as $occurrence ) {
|
|
||||||
if ( $begin !== null && $occurrence < $begin ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( $end !== null && $occurrence > $end ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$res[] = clone $occurrence;
|
|
||||||
$n += 1;
|
|
||||||
if ( $limit && $n >= $limit ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if $date is an occurrence.
|
* Return true if $date is an occurrence.
|
||||||
*
|
*
|
||||||
@ -1130,38 +1058,6 @@ class RRule implements RRuleInterface
|
|||||||
// Internal methods
|
// Internal methods
|
||||||
// where all the magic happens
|
// where all the magic happens
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert any date into a DateTime object.
|
|
||||||
*
|
|
||||||
* @param mixed $date
|
|
||||||
* @return \DateTime
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException on error
|
|
||||||
*/
|
|
||||||
static public function parseDate($date)
|
|
||||||
{
|
|
||||||
// DateTimeInterface is only on PHP 5.5+, and includes DateTimeImmutable
|
|
||||||
if ( ! $date instanceof \DateTime && ! $date instanceof \DateTimeInterface ) {
|
|
||||||
try {
|
|
||||||
if ( is_integer($date) ) {
|
|
||||||
$date = \DateTime::createFromFormat('U',$date);
|
|
||||||
$date->setTimezone(new \DateTimeZone('UTC')); // default is +00:00 (see issue #15)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$date = new \DateTime($date);
|
|
||||||
}
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
"Failed to parse the date"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$date = clone $date; // avoid reference problems
|
|
||||||
}
|
|
||||||
return $date;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of days of the year (numbered from 0 to 365)
|
* Return an array of days of the year (numbered from 0 to 365)
|
||||||
* of the current timeframe (year, month, week, day) containing the current date
|
* of the current timeframe (year, month, week, day) containing the current date
|
||||||
|
@ -29,11 +29,58 @@ interface RRuleInterface extends \ArrayAccess, \Countable, \IteratorAggregate
|
|||||||
*
|
*
|
||||||
* @param mixed $begin Can be null to return all occurrences before $end
|
* @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 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)
|
* @param int|null $limit Limit the resultset to n occurrences (0, null or false = everything)
|
||||||
* @return array An array of \DateTime objects
|
* @return array An array of \DateTime objects
|
||||||
*/
|
*/
|
||||||
public function getOccurrencesBetween($begin, $end, $limit = null);
|
public function getOccurrencesBetween($begin, $end, $limit = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all the occurrences after a date.
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @param bool $inclusive Whether or not to include $date (if date is an occurrence)
|
||||||
|
* @param int|null $limit Limit the resultset to n occurrences (0, null or false = everything)
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getOccurrencesAfter($date, $inclusive = false, $limit = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Nth occurrences after a date (non inclusive)
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @param int $index The index (starts at 1)
|
||||||
|
* @return DateTimeInterface|null
|
||||||
|
*/
|
||||||
|
public function getNthOccurrenceAfter($date, $index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all the occurrences before a date.
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @param bool $inclusive Whether or not to include $date (if date is an occurrence)
|
||||||
|
* @param int|null $limit Limit the resultset to n occurrences (0, null or false = everything)
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getOccurrencesBefore($date, $inclusive = false, $limit = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Nth occurrences before a date (non inclusive)
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @param int $index The index (starts at 1)
|
||||||
|
* @return DateTimeInterface|null
|
||||||
|
*/
|
||||||
|
public function getNthOccurrenceBefore($date, $index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Nth occurrences before or after a date.
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @param int $index 0 returns the date, positive integer returns index in the future, negative in the past
|
||||||
|
* @return DateTimeInterface|null
|
||||||
|
*/
|
||||||
|
public function getNthOccurrenceFrom($date, $index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if $date is an occurrence.
|
* Return true if $date is an occurrence.
|
||||||
*
|
*
|
||||||
|
203
src/RRuleTrait.php
Executable file
203
src/RRuleTrait.php
Executable file
@ -0,0 +1,203 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Licensed under the MIT license.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE file.
|
||||||
|
*
|
||||||
|
* @author Rémi Lanvin <remi@cloudconnected.fr>
|
||||||
|
* @link https://github.com/rlanvin/php-rrule
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace RRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement the common methods of the RRuleInterface used by RRule and RSet
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
trait RRuleTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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($limit = null)
|
||||||
|
{
|
||||||
|
if ( ! $limit && $this->isInfinite() ) {
|
||||||
|
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
|
||||||
|
}
|
||||||
|
if ( $limit !== null && $limit !== false && $limit < 0 ) {
|
||||||
|
throw new \InvalidArgumentException('$limit cannot be negative');
|
||||||
|
}
|
||||||
|
|
||||||
|
// cached version already computed
|
||||||
|
$iterator = $this;
|
||||||
|
if ( $this->total !== null ) {
|
||||||
|
$iterator = $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = array();
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, $limit = null)
|
||||||
|
{
|
||||||
|
if ( $begin !== null ) {
|
||||||
|
$begin = self::parseDate($begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $end !== null ) {
|
||||||
|
$end = self::parseDate($end);
|
||||||
|
}
|
||||||
|
elseif ( ! $limit && $this->isInfinite() ) {
|
||||||
|
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $limit !== null && $limit !== false && $limit < 0 ) {
|
||||||
|
throw new \InvalidArgumentException('$limit cannot be negative');
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = $this;
|
||||||
|
if ( $this->total !== null ) {
|
||||||
|
$iterator = $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = array();
|
||||||
|
$n = 0;
|
||||||
|
foreach ( $iterator as $occurrence ) {
|
||||||
|
if ( $begin !== null && $occurrence < $begin ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( $end !== null && $occurrence > $end ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$res[] = clone $occurrence;
|
||||||
|
$n += 1;
|
||||||
|
if ( $limit && $n >= $limit ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOccurrencesAfter($date, $inclusive = false, $limit = null)
|
||||||
|
{
|
||||||
|
if ( $inclusive || ! $this->occursAt($date) ) {
|
||||||
|
return $this->getOccurrencesBetween($date, null, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
$limit += 1;
|
||||||
|
$occurrences = $this->getOccurrencesBetween($date, null, $limit);
|
||||||
|
return array_slice($occurrences, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNthOccurrenceAfter($date, $index)
|
||||||
|
{
|
||||||
|
if ( $index <= 0 ) {
|
||||||
|
throw new \InvalidArgumentException("Index must be a positive integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
$occurrences = $this->getOccurrencesAfter($date, false, $index);
|
||||||
|
|
||||||
|
return isset($occurrences[$index-1]) ? $occurrences[$index-1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOccurrencesBefore($date, $inclusive = false, $limit = null)
|
||||||
|
{
|
||||||
|
// we need to get everything
|
||||||
|
$occurrences = $this->getOccurrencesBetween(null, $date);
|
||||||
|
|
||||||
|
if ( ! $inclusive && $this->occursAt($date) ) {
|
||||||
|
array_pop($occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the limit is counted from $date
|
||||||
|
if ( $limit ) {
|
||||||
|
$occurrences = array_slice($occurrences, -1 * $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $occurrences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNthOccurrenceBefore($date, $index)
|
||||||
|
{
|
||||||
|
if ( $index <= 0 ) {
|
||||||
|
throw new \InvalidArgumentException("Index must be a positive integer");
|
||||||
|
}
|
||||||
|
|
||||||
|
$occurrences = $this->getOccurrencesBefore($date, false, $index);
|
||||||
|
|
||||||
|
if ( sizeof($occurrences) < $index ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $occurrences[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNthOccurrenceFrom($date, $index)
|
||||||
|
{
|
||||||
|
if ( ! is_numeric($index) ) {
|
||||||
|
throw new \InvalidArgumentException('Malformed index (must be a numeric)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $index == 0 ) {
|
||||||
|
return $this->occursAt($date) ? self::parseDate($date) : null;
|
||||||
|
}
|
||||||
|
elseif ( $index > 0 ) {
|
||||||
|
return $this->getNthOccurrenceAfter($date, $index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $this->getNthOccurrenceBefore($date, -1*$index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Convert any date into a DateTime object.
|
||||||
|
*
|
||||||
|
* @param mixed $date
|
||||||
|
* @return \DateTime
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException on error
|
||||||
|
*/
|
||||||
|
static public function parseDate($date)
|
||||||
|
{
|
||||||
|
// DateTimeInterface is only on PHP 5.5+, and includes DateTimeImmutable
|
||||||
|
if ( ! $date instanceof \DateTime && ! $date instanceof \DateTimeInterface ) {
|
||||||
|
try {
|
||||||
|
if ( is_integer($date) ) {
|
||||||
|
$date = \DateTime::createFromFormat('U',$date);
|
||||||
|
$date->setTimezone(new \DateTimeZone('UTC')); // default is +00:00 (see issue #15)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$date = new \DateTime($date);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
"Failed to parse the date"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$date = clone $date; // avoid reference problems
|
||||||
|
}
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
|
}
|
46
src/RSet.php
46
src/RSet.php
@ -16,6 +16,8 @@ namespace RRule;
|
|||||||
*/
|
*/
|
||||||
class RSet implements RRuleInterface
|
class RSet implements RRuleInterface
|
||||||
{
|
{
|
||||||
|
use RRuleTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array List of RDATE (single dates)
|
* @var array List of RDATE (single dates)
|
||||||
*/
|
*/
|
||||||
@ -348,50 +350,6 @@ class RSet implements RRuleInterface
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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, $limit = null)
|
|
||||||
{
|
|
||||||
if ( $begin !== null ) {
|
|
||||||
$begin = RRule::parseDate($begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $end !== null ) {
|
|
||||||
$end = RRule::parseDate($end);
|
|
||||||
}
|
|
||||||
elseif ( ! $limit && $this->isInfinite() ) {
|
|
||||||
throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$iterator = $this;
|
|
||||||
if ( $this->total !== null ) {
|
|
||||||
$iterator = $this->cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
$res = array();
|
|
||||||
$n = 0;
|
|
||||||
foreach ( $iterator as $occurrence ) {
|
|
||||||
if ( $begin !== null && $occurrence < $begin ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( $end !== null && $occurrence > $end ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$res[] = clone $occurrence;
|
|
||||||
$n += 1;
|
|
||||||
if ( $limit && $n >= $limit ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if $date is an occurrence.
|
* Return true if $date is an occurrence.
|
||||||
*
|
*
|
||||||
|
@ -1777,17 +1777,46 @@ class RRuleTest extends TestCase
|
|||||||
$rrule->getOccurrences();
|
$rrule->getOccurrences();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetOccurrencesBetween()
|
public function testGetOccurrencesNegativeLimit()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
$rrule = new RRule(array(
|
$rrule = new RRule(array(
|
||||||
'FREQ' => 'DAILY',
|
'FREQ' => 'DAILY',
|
||||||
'DTSTART' => '2017-01-01'
|
'DTSTART' => '2017-01-01'
|
||||||
));
|
));
|
||||||
|
$rrule->getOccurrences(-1);
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertCount(1, $rrule->getOccurrencesBetween('2017-01-01', null, 1));
|
public function occurrencesBetween()
|
||||||
$this->assertCount(1, $rrule->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
|
{
|
||||||
$this->assertEquals(array(date_create('2017-02-01')), $rrule->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
|
return [
|
||||||
$this->assertCount(5, $rrule->getOccurrencesBetween('2017-01-01', null, 5));
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', null, 1, [date_create('2017-01-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-02-01', '2017-12-31', 1, [date_create('2017-02-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', null, 5, [
|
||||||
|
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'),
|
||||||
|
]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', '2017-01-05', null, [
|
||||||
|
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'),
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider occurrencesBetween
|
||||||
|
*/
|
||||||
|
public function testGetOccurrencesBetween($rule, $begin, $end, $limit, $expected)
|
||||||
|
{
|
||||||
|
$rrule = new RRule($rule);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $rrule->getOccurrencesBetween($begin, $end, $limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1803,6 +1832,89 @@ class RRuleTest extends TestCase
|
|||||||
$rrule->getOccurrencesBetween('2017-01-01', null);
|
$rrule->getOccurrencesBetween('2017-01-01', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetOccurrencesBetweenNegativeLimit()
|
||||||
|
{
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
$rrule = new RRule(array(
|
||||||
|
'FREQ' => 'DAILY',
|
||||||
|
'DTSTART' => '2017-01-01'
|
||||||
|
));
|
||||||
|
$rrule->getOccurrencesBetween('2017-01-01', '2018-01-01', -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function occurrencesAfter()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-02-01', false, 2, [date_create('2017-02-02'),date_create('2017-02-03')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-02-01', true, 2, [date_create('2017-02-01'),date_create('2017-02-02')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-02', true, 2, [date_create('2017-01-03'),date_create('2017-01-05')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-02', false, 2, [date_create('2017-01-03'),date_create('2017-01-05')]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider occurrencesAfter
|
||||||
|
*/
|
||||||
|
public function testGetOccurrencesAfter($rrule, $date, $inclusive, $limit, $expected)
|
||||||
|
{
|
||||||
|
$rrule = new RRule($rrule);
|
||||||
|
$occurrences = $rrule->getOccurrencesAfter($date, $inclusive, $limit);
|
||||||
|
$this->assertEquals($expected, $occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function occurrencesBefore()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-02-01', true, 2, [date_create('2017-01-31'),date_create('2017-02-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-02-01', false, 2, [date_create('2017-01-30'),date_create('2017-01-31')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-02', false, null, [date_create('2017-01-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-02', false, 5, [date_create('2017-01-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-04', true, 2, [date_create('2017-01-01'),date_create('2017-01-03')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-04', false, 2, [date_create('2017-01-01'),date_create('2017-01-03')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-02', false, null, [date_create('2017-01-01')]],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-02', false, 5, [date_create('2017-01-01')]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @dataProvider occurrencesBefore
|
||||||
|
*/
|
||||||
|
public function testGetOccurrencesBefore($rrule, $date, $inclusive, $limit, $expected)
|
||||||
|
{
|
||||||
|
$rrule = new RRule($rrule);
|
||||||
|
$occurrences = $rrule->getOccurrencesBefore($date, $inclusive, $limit);
|
||||||
|
$this->assertEquals($expected, $occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function nthOccurrences()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', 0, date_create('2017-01-01')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', 1, date_create('2017-01-02')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-01', 2, date_create('2017-01-05')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-02', 0, null],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-01', -1, null],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-10', -1, date_create('2017-01-09')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY", '2017-01-10', -2, date_create('2017-01-08')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-11', -2, date_create('2017-01-07')],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2", '2017-01-10', -2, date_create('2017-01-07')],
|
||||||
|
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;COUNT=2", '2017-01-01', 3, null],
|
||||||
|
["DTSTART:20170101\nRRULE:FREQ=DAILY;UNTIL=20170102", '2017-01-01', 3, null],
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider nthOccurrences
|
||||||
|
*/
|
||||||
|
public function testGetNthOccurrenceFrom($rrule, $date, $index, $result)
|
||||||
|
{
|
||||||
|
$rrule = new RRule($rrule);
|
||||||
|
$occurrence = $rrule->getNthOccurrenceFrom($date, $index);
|
||||||
|
$this->assertEquals($result, $occurrence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RFC Strings
|
// RFC Strings
|
||||||
|
|
||||||
|
@ -468,19 +468,34 @@ class RSetTest extends TestCase
|
|||||||
)));
|
)));
|
||||||
$rset->getOccurrences();
|
$rset->getOccurrences();
|
||||||
}
|
}
|
||||||
|
public function occurrencesBetween()
|
||||||
public function testGetOccurrencesBetween()
|
|
||||||
{
|
{
|
||||||
$rset = new RSet();
|
return [
|
||||||
$rset->addRRule(new RRule(array(
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', null, 1, [date_create('2017-01-01')]],
|
||||||
'FREQ' => 'DAILY',
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-02-01', '2017-12-31', 1, [date_create('2017-02-01')]],
|
||||||
'DTSTART' => '2017-01-01'
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', null, 5, [
|
||||||
)));
|
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'),
|
||||||
|
]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', '2017-01-05', null, [
|
||||||
|
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'),
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertCount(1, $rset->getOccurrencesBetween('2017-01-01', null, 1));
|
/**
|
||||||
$this->assertCount(1, $rset->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
|
* @dataProvider occurrencesBetween
|
||||||
$this->assertEquals(array(date_create('2017-02-01')), $rset->getOccurrencesBetween('2017-02-01', '2017-12-31', 1));
|
*/
|
||||||
$this->assertCount(5, $rset->getOccurrencesBetween('2017-01-01', null, 5));
|
public function testGetOccurrencesBetween(RSet $rset, $begin, $end, $limit, $expected)
|
||||||
|
{
|
||||||
|
$this->assertEquals($expected, $rset->getOccurrencesBetween($begin, $end, $limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -497,6 +512,79 @@ class RSetTest extends TestCase
|
|||||||
$rset->getOccurrencesBetween('2017-01-01', null);
|
$rset->getOccurrencesBetween('2017-01-01', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function occurrencesAfter()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
(new RSet())
|
||||||
|
->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2")
|
||||||
|
->addRRule("DTSTART:20170102\nRRULE:FREQ=DAILY;INTERVAL=2")
|
||||||
|
, '2017-02-01', false, 2, [date_create('2017-02-02'),date_create('2017-02-03')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-02-01', true, 2, [date_create('2017-02-01'),date_create('2017-02-02')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-02', true, 2, [date_create('2017-01-03'),date_create('2017-01-05')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-02', false, 2, [date_create('2017-01-03'),date_create('2017-01-05')]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider occurrencesAfter
|
||||||
|
*/
|
||||||
|
public function testGetOccurrencesAfter(RSet $rset, $date, $inclusive, $limit, $expected)
|
||||||
|
{
|
||||||
|
$occurrences = $rset->getOccurrencesAfter($date, $inclusive, $limit);
|
||||||
|
$this->assertEquals($expected, $occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function occurrencesBefore()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-02-01', true, 2, [date_create('2017-01-31'),date_create('2017-02-01')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-02-01', false, 2, [date_create('2017-01-30'),date_create('2017-01-31')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-02', false, null, [date_create('2017-01-01')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-02', false, 5, [date_create('2017-01-01')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-04', true, 2, [date_create('2017-01-01'),date_create('2017-01-03')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-04', false, 2, [date_create('2017-01-01'),date_create('2017-01-03')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-02', false, null, [date_create('2017-01-01')]],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-02', false, 5, [date_create('2017-01-01')]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @dataProvider occurrencesBefore
|
||||||
|
*/
|
||||||
|
public function testGetOccurrencesBefore(RSet $rset, $date, $inclusive, $limit, $expected)
|
||||||
|
{
|
||||||
|
$occurrences = $rset->getOccurrencesBefore($date, $inclusive, $limit);
|
||||||
|
$this->assertEquals($expected, $occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function nthOccurrences()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', 0, date_create('2017-01-01')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', 1, date_create('2017-01-02')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-01', 2, date_create('2017-01-05')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-02', 0, null],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-01', -1, null],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-10', -1, date_create('2017-01-09')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY"), '2017-01-10', -2, date_create('2017-01-08')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-11', -2, date_create('2017-01-07')],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;INTERVAL=2"), '2017-01-10', -2, date_create('2017-01-07')],
|
||||||
|
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;COUNT=2"), '2017-01-01', 3, null],
|
||||||
|
[(new RSet())->addRRule("DTSTART:20170101\nRRULE:FREQ=DAILY;UNTIL=20170102"), '2017-01-01', 3, null],
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider nthOccurrences
|
||||||
|
*/
|
||||||
|
public function testGetNthOccurrenceFrom(RSet $rset, $date, $index, $result)
|
||||||
|
{
|
||||||
|
$occurrence = $rset->getNthOccurrenceFrom($date, $index);
|
||||||
|
$this->assertEquals($result, $occurrence);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RFC Strings
|
// RFC Strings
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user