PHP Class RRule\RRule

Heavily based on python-dateutil/rrule Some useful terms to understand the algorithms and variables naming: yearday = day of the year, from 0 to 365 (on leap years) - date('z') weekday = day of the week (ISO-8601), from 1 (MO) to 7 (SU) - date('N') monthday = day of the month, from 1 to 31 wkst = week start, the weekday (1 to 7) which is the first day of week. Default is Monday (1). In some countries it's Sunday (7). weekno = number of the week in the year (ISO-8601) CAREFUL with this bug: https://bugs.php.net/bug.php?id=62476
See also: https://tools.ietf.org/html/rfc5545
See also: https://labix.org/python-dateutil
Inheritance: implements Iterator, implements ArrayAccess, implements Countable
Mostra file Open project: rlanvin/php-rrule Class Usage Examples

Public Properties

Property Type Description
$frequencies frequency names
$week_days weekdays numbered from 1 (ISO-8601 or date('N'))

Protected Properties

Property Type Description
$LAST_DAY_OF_MONTH array
$LAST_DAY_OF_MONTH_366 array
$MONTHDAY_MASK array
$MONTHDAY_MASK_366 array
$MONTH_MASK array
$MONTH_MASK_366 array
$NEGATIVE_MONTHDAY_MASK array
$NEGATIVE_MONTHDAY_MASK_366 array
$REPEAT_CYCLES array Maximum number of cycles after which a calendar repeats itself. This is used to detect infinite loop: if no occurrence has been found after this numbers of cycles, we can abort. The Gregorian calendar cycle repeat completely every 400 years (146,097 days or 20,871 weeks). A smaller cycle would be 28 years (1,461 weeks), but it only works if there is no dropped leap year in between. 2100 will be a dropped leap year, but I'm going to assume it's not going to be a problem anytime soon, so at the moment I use the 28 years cycle.
$WEEKDAY_MASK array
$byhour
$byminute
$bymonth
$bymonthday
$bymonthday_negative
$bysecond
$bysetpos
$byweekday
$byweekday_nth
$byweekno
$byyearday
$cache
$count
$current
$dtstart parsed and validated values
$freq
$i18n Stores translations once loaded (so we don't have to reload them all the time)
$interval
$intl_loaded
$key
$rule original rule
$timeset
$total cache variables
$until
$wkst

Public Methods

Method Description
__construct ( mixed $parts ) The constructor needs the entire rule at once.
__toString ( ) : string Magic string converter.
clearCache ( ) Clear the cache.
count ( ) : integer Returns the number of occurrences in this rule. It will have go through the whole recurrence, if this hasn't been done before, which introduces a performance penality.
current ( )
getOccurrences ( ) : array Return all the occurrences in an array of \DateTime.
getOccurrencesBetween ( mixed $begin, mixed $end ) : array Return all the ocurrences after a date, before a date, or between two dates.
getRule ( ) : array Return the internal rule array, as it was passed to the constructor.
humanReadable ( array $opt = [] ) : string Format a rule in a human readable string intl extension is required.
isFinite ( ) : boolean Return true if the rrule has an end condition, false otherwise
isInfinite ( ) : boolean Return true if the rrule has no end condition (infite)
key ( )
next ( )
occursAt ( mixed $date ) : boolean Return true if $date is an occurrence.
offsetExists ( $offset )
offsetGet ( $offset )
offsetSet ( $offset, $value )
offsetUnset ( $offset )
parseDate ( mixed $date ) : DateTime Convert any date into a DateTime object.
parseRfcString ( string $string ) : array Take a RFC 5545 string and returns an array (to be given to the constructor)
rewind ( )
rfcString ( boolean $include_timezone = true ) : string Format a rule according to RFC 5545
valid ( )

Protected Methods

Method Description
buildNthWeekdayMask ( integer $year, integer $month, integer $day, array &$masks ) : null Calculate the yeardays corresponding to each Nth weekday (in BYDAY rule part).
buildWeeknoMask ( integer $year, integer $month, integer $day, array &$masks ) : null Calculate the yeardays corresponding to the week number (in the WEEKNO rule part).
getDaySet ( integer $year, integer $month, integer $day, array $masks ) : array 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
getTimeSet ( integer $hour, integer $minute, integer $second ) : array Build an array of every time of the day that matches the BYXXX time criteria.
i18nList ( array $array, string $and = 'and' ) : string Create a comma-separated list, with the last item added with an " and " Example: Monday, Tuesday and Friday
i18nLoad ( string $locale, string | null $fallback = null ) : array Load a translation file in memory.
i18nSelect ( mixed $array, string $n ) : string Select a translation in $array based on the value of $n
iterate ( $reset = false ) : DateTime | null This is the main method, where all of the magic happens.

Method Details

__construct() public method

There is no setter after the class has been instanciated, because in order to validate some BYXXX parts, we need to know the value of some other parts (FREQ or other BXXX parts).
public __construct ( mixed $parts )
$parts mixed An assoc array of parts, or a RFC string.

__toString() public method

Magic string converter.
See also: RRule::rfcString()
public __toString ( ) : string
return string a rfc string

buildNthWeekdayMask() protected method

For example, in Jan 1998, in a MONTHLY interval, "1SU,-1SU" (first Sunday and last Sunday) would be transformed into [3=>true,24=>true] because the first Sunday of Jan 1998 is yearday 3 (counting from 0) and the last Sunday of Jan 1998 is yearday 24 (counting from 0).
protected buildNthWeekdayMask ( integer $year, integer $month, integer $day, array &$masks ) : null
$year integer
$month integer
$day integer
$masks array
return null (modifies $mask parameter)

buildWeeknoMask() protected method

Because weeks can cross year boundaries (that is, week #1 can start the previous year, and week 52/53 can continue till the next year), the algorithm is quite long.
protected buildWeeknoMask ( integer $year, integer $month, integer $day, array &$masks ) : null
$year integer
$month integer
$day integer
$masks array
return null (modifies $mask)

clearCache() public method

It isn't recommended to use this method while iterating.
public clearCache ( )

count() public method

Returns the number of occurrences in this rule. It will have go through the whole recurrence, if this hasn't been done before, which introduces a performance penality.
public count ( ) : integer
return integer

current() public method

public current ( )

getDaySet() protected method

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
protected getDaySet ( integer $year, integer $month, integer $day, array $masks ) : array
$year integer
$month integer
$day integer
$masks array
return array

getOccurrences() public method

Return all the occurrences in an array of \DateTime.
public getOccurrences ( ) : array
return array An array of \DateTime objects

getOccurrencesBetween() public method

Return all the ocurrences after a date, before a date, or between two dates.
public getOccurrencesBetween ( mixed $begin, mixed $end ) : array
$begin mixed Can be null to return all occurrences before $end
$end mixed Can be null to return all occurrences after $begin
return array An array of \DateTime objects

getRule() public method

Return the internal rule array, as it was passed to the constructor.
public getRule ( ) : array
return array

getTimeSet() protected method

It will only process $this->frequency at one time. So: - for HOURLY frequencies it builds the minutes and second of the given hour - for MINUTELY frequencies it builds the seconds of the given minute - for SECONDLY frequencies, it returns an array with one element This method is called everytime an increment of at least one hour is made.
protected getTimeSet ( integer $hour, integer $minute, integer $second ) : array
$hour integer
$minute integer
$second integer
return array

humanReadable() public method

Format a rule in a human readable string intl extension is required.
public humanReadable ( array $opt = [] ) : string
$opt array
return string

i18nList() protected static method

Create a comma-separated list, with the last item added with an " and " Example: Monday, Tuesday and Friday
protected static i18nList ( array $array, string $and = 'and' ) : string
$array array
$and string Translation for "and"
return string

i18nLoad() protected static method

Will load the basic first (e.g. "en") and then the region-specific if any (e.g. "en_GB"), merging as necessary. So region-specific translation files don't need to redefine every strings.
protected static i18nLoad ( string $locale, string | null $fallback = null ) : array
$locale string
$fallback string | null
return array

i18nSelect() protected static method

Used for selecting plural forms.
protected static i18nSelect ( mixed $array, string $n ) : string
$array mixed Array with multiple forms or a string
$n string
return string

isFinite() public method

Return true if the rrule has an end condition, false otherwise
public isFinite ( ) : boolean
return boolean

isInfinite() public method

Return true if the rrule has no end condition (infite)
public isInfinite ( ) : boolean
return boolean

iterate() protected method

This method is a generator that works for PHP 5.3/5.4 (using static variables) The main idea is: a brute force made fast by not relying on date() functions There is one big loop that examines every interval of the given frequency (so every day, every week, every month or every year), constructs an array of all the yeardays of the interval (for daily frequencies, the array only has one element, for weekly 7, and so on), and then filters out any day that do no match BYXXX parts. The algorithm does not try to be "smart" in calculating the increment of the loop. That is, for a rule like "every day in January for 10 years" the algorithm will loop through every day of the year, each year, generating some 3650 iterations (+ some to account for the leap years). This is a bit counter-intuitive, as it is obvious that the loop could skip all the days in February till December since they are never going to match. Fortunately, this approach is still super fast because it doesn't rely on date() or DateTime functions, and instead does all the date operations manually, either arithmetically or using arrays as converters. Another quirk of this approach is that because the granularity is by day, higher frequencies (hourly, minutely and secondly) have to have their own special loops within the main loop, making the whole thing quite convoluted. Moreover, at such frequencies, the brute-force approach starts to really suck. For example, a rule like "Every minute, every Jan 1st between 10:00 and 10:59, for 10 years" requires a tremendous amount of useless iterations to jump from Jan 1st 10:59 at year 1 to Jan 1st 10.00 at year 2. In order to make a "smart jump", we would have to have a way to determine the gap between the next occurence arithmetically. I think that would require to analyze each "BYXXX" rule part that "Limit" the set (see the RFC page 43) at the given frequency. For example, a YEARLY frequency doesn't need "smart jump" at all; MONTHLY and WEEKLY frequencies only need to check BYMONTH; DAILY frequency needs to check BYMONTH, BYMONTHDAY and BYDAY, and so on. The check probably has to be done in reverse order, e.g. for DAILY frequencies attempt to jump to the next weekday (BYDAY) or next monthday (BYMONTHDAY) (I don't know yet which one first), and then if that results in a change of month, attempt to jump to the next BYMONTH, and so on.
protected iterate ( $reset = false ) : DateTime | null
$reset (bool) Whether to restart the iteration, or keep going
return DateTime | null

key() public method

public key ( )

next() public method

public next ( )

occursAt() public method

This method will attempt to determine the result programmatically. However depending on the BYXXX rule parts that have been set, it might not always be possible. As a last resort, this method will loop through all occurrences until $date. This will incurr some performance penalty.
public occursAt ( mixed $date ) : boolean
$date mixed
return boolean

offsetExists() public method

public offsetExists ( $offset )

offsetGet() public method

public offsetGet ( $offset )

offsetSet() public method

public offsetSet ( $offset, $value )

offsetUnset() public method

public offsetUnset ( $offset )

parseDate() public static method

Convert any date into a DateTime object.
public static parseDate ( mixed $date ) : DateTime
$date mixed
return DateTime

parseRfcString() public static method

Take a RFC 5545 string and returns an array (to be given to the constructor)
public static parseRfcString ( string $string ) : array
$string string The rule to be parsed
return array

rewind() public method

public rewind ( )

rfcString() public method

Format a rule according to RFC 5545
public rfcString ( boolean $include_timezone = true ) : string
$include_timezone boolean Wether to generate a rule with timezone identifier on DTSTART (and UNTIL) or not.
return string

valid() public method

public valid ( )

Property Details

$LAST_DAY_OF_MONTH protected_oe static_oe property

protected static array $LAST_DAY_OF_MONTH
return array

$LAST_DAY_OF_MONTH_366 protected_oe static_oe property

protected static array $LAST_DAY_OF_MONTH_366
return array

$MONTHDAY_MASK protected_oe static_oe property

protected static array $MONTHDAY_MASK
return array

$MONTHDAY_MASK_366 protected_oe static_oe property

protected static array $MONTHDAY_MASK_366
return array

$MONTH_MASK protected_oe static_oe property

protected static array $MONTH_MASK
return array

$MONTH_MASK_366 protected_oe static_oe property

protected static array $MONTH_MASK_366
return array

$NEGATIVE_MONTHDAY_MASK protected_oe static_oe property

protected static array $NEGATIVE_MONTHDAY_MASK
return array

$NEGATIVE_MONTHDAY_MASK_366 protected_oe static_oe property

protected static array $NEGATIVE_MONTHDAY_MASK_366
return array

$REPEAT_CYCLES protected_oe static_oe property

Maximum number of cycles after which a calendar repeats itself. This is used to detect infinite loop: if no occurrence has been found after this numbers of cycles, we can abort. The Gregorian calendar cycle repeat completely every 400 years (146,097 days or 20,871 weeks). A smaller cycle would be 28 years (1,461 weeks), but it only works if there is no dropped leap year in between. 2100 will be a dropped leap year, but I'm going to assume it's not going to be a problem anytime soon, so at the moment I use the 28 years cycle.
protected static array $REPEAT_CYCLES
return array

$WEEKDAY_MASK protected_oe static_oe property

protected static array $WEEKDAY_MASK
return array

$byhour protected_oe property

protected $byhour

$byminute protected_oe property

protected $byminute

$bymonth protected_oe property

protected $bymonth

$bymonthday protected_oe property

protected $bymonthday

$bymonthday_negative protected_oe property

protected $bymonthday_negative

$bysecond protected_oe property

protected $bysecond

$bysetpos protected_oe property

protected $bysetpos

$byweekday protected_oe property

protected $byweekday

$byweekday_nth protected_oe property

protected $byweekday_nth

$byweekno protected_oe property

protected $byweekno

$byyearday protected_oe property

protected $byyearday

$cache protected_oe property

protected $cache

$count protected_oe property

protected $count

$current protected_oe property

protected $current

$dtstart protected_oe property

parsed and validated values
protected $dtstart

$freq protected_oe property

protected $freq

$frequencies public_oe static_oe property

frequency names
public static $frequencies

$i18n protected_oe static_oe property

Stores translations once loaded (so we don't have to reload them all the time)
protected static $i18n

$interval protected_oe property

protected $interval

$intl_loaded protected_oe static_oe property

protected static $intl_loaded

$key protected_oe property

protected $key

$rule protected_oe property

original rule
protected $rule

$timeset protected_oe property

protected $timeset

$total protected_oe property

cache variables
protected $total

$until protected_oe property

protected $until

$week_days public_oe static_oe property

weekdays numbered from 1 (ISO-8601 or date('N'))
public static $week_days

$wkst protected_oe property

protected $wkst