Documentation

RecurrenceIterator
in package
implements Iterator

Iterator to calculate all occurrences of a recurring event.

Table of Contents

Interfaces

Iterator

Constants

DEFAULT_COUNTS  = ['YEARLY' => 10, 'MONTHLY' => 12, 'WEEKLY' => 52, 'DAILY' => 365, 'HOURLY' => 720, 'MINUTELY' => 1440, 'SECONDLY' => 3600]
TYPE_ABSOLUTE  = 0
TYPE_ALLDAY  = 2
TYPE_FLOATING  = 1
WEEKDAY_NAMES  = ['MO' => 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday', 'SU' => 'Sunday']

Properties

$by  : array<string|int, mixed>
$dtstart  : DateTimeInterface
$exdates  : array<string|int, mixed>
$frequency_interval  : DateInterval
$key  : int
$limit_after  : DateTimeImmutable
$limit_before  : DateTimeImmutable
$max_occurrences  : int|float
$occurrences  : array<string|int, mixed>
$rdates  : array<string|int, mixed>
$record_format  : string
$rrule  : RRule
$rrule_occurrences  : array<string|int, mixed>
$type  : int
$view_end  : DateTimeImmutable
$view_start  : DateTimeImmutable

Methods

__construct()  : mixed
Constructor.
add()  : void
Adds an arbitrary date to the recurrence set.
calculateWeekNum()  : int
Calculates the week number of a date according to RFC 5545.
current()  : DateTimeInterface|false
Returns a \DateTimeInterface object for the currently selected element in the event's recurrence set.
dateOccurs()  : bool
Checks whether the given date/time occurs in the recurrence set.
end()  : void
Moves the iterator key to the end.
getDtStart()  : DateTimeInterface
Returns a copy of $this->dtstart.
getExDates()  : array<string|int, mixed>
Returns a copy of $this->exdates.
getFrequencyInterval()  : DateInterval
Returns a copy of $this->frequency_interval.
getNext()  : DateTimeInterface|false
Moves the iterator key one step forward, and then returns a DateTimeInterface object for the newly selected element in the event's recurrence set.
getPrev()  : DateTimeInterface|false
Moves the iterator key one step backward, and then returns a DateTimeInterface object for the newly selected element in the event's recurrence set.
getRDates()  : array<string|int, mixed>
Returns a copy of $this->rdates.
getRRule()  : RRule
Returns a copy of the recurrence rule.
getRRuleOccurrences()  : array<string|int, mixed>
Returns occurrences generated by the RRule only.
key()  : int
Get the current value of the iterator key.
next()  : void
Moves the iterator key one step forward.
prev()  : void
Moves the iterator key one step backward.
remove()  : void
Removes a date from the recurrence set.
rewind()  : void
Moves the iterator key back to the beginning.
search()  : int|false
Finds the iterator key that corresponds to the requested value.
setKey()  : int
Moves the iterator key to a specific position.
valid()  : bool
Checks whether the current value of the iterator key is valid.
calculate()  : void
Calculates occurrences based on the recurrence rule.
expand()  : Generator<string|int, DateTimeImmutable>
Finds additional occurrences based on any BYxxx rule parts in the RRule.
expandMonthByDay()  : Generator<string|int, DateTimeImmutable>
Used when expanding an occurrence that is part of a monthly recurrence set that has a byday rule, or part of a yearly recurrence set that has both a bymonth rule and a byday rule.
expandYearByDay()  : Generator<string|int, DateTimeImmutable>
Used when expanding an occurrence that is part of a yearly recurrence set that has a byday rule but not a bymonth rule.
jumpToVisible()  : void
If possible, move $current ahead in order to skip values before $this->view_start.
limit()  : bool
Checks whether a calculated occurrence should be included based on BYxxx rule parts in the RRule.
limitBySetPos()  : void
Applies BYSETPOS limitation to the reccurrence set.
nextInterval()  : void
Move $current ahead to the next interval.
record()  : bool
Adds an occurrence to $this->occurrences.
setFrequencyInterval()  : void
Sets the value of $this->frequency_interval.
sortWeekdays()  : array<string|int, mixed>
Sorts an array of weekday abbreviations so that $this->rrule->wkst is always the first item.

Constants

DEFAULT_COUNTS

public array<string|int, mixed> DEFAULT_COUNTS = ['YEARLY' => 10, 'MONTHLY' => 12, 'WEEKLY' => 52, 'DAILY' => 365, 'HOURLY' => 720, 'MINUTELY' => 1440, 'SECONDLY' => 3600]

Used to calculate a default value for $this->view_end.

These are only used when the RRule repeats forever and no value was specified for the constructor's $view parameter.

Keys are possible values of $this->rrule->freq. Values are the number of times to add $this->frequency_interval to $this->view_start in order to calculate $this->view_end.

These defaults are entirely arbitrary choices by the developer. ;)

TYPE_ABSOLUTE

public int TYPE_ABSOLUTE = 0

Indicates that the event has a date, time, and time zone.

For example, an absolute event on '2023-10-26 14:00:00 Europe/Paris' will occur on Oct 26, 2023, at 2:00 PM for a user in Paris, France, but at 8:00 AM for a user in Toronto, Canada, and at 11:00 PM for a user in Sydney, Australia.

TYPE_ALLDAY

public int TYPE_ALLDAY = 2

Indicates that the event has a specific date, but no time or time zone.

For example, an all day event on '2023-10-26' will occur on Oct 26, 2023, starting at midnight in whatever time zone the viewer happens to be in, and ending on the following midnight in that time zone.

TYPE_FLOATING

public int TYPE_FLOATING = 1

Indicates that the event has specific date and time, but no time zone.

For example, a floating event on '2023-10-26 14:00:00' will occur on Oct 26, 2023, at 2:00 PM in whatever time zone the viewer happens to currently be in.

WEEKDAY_NAMES

public array<string|int, mixed> WEEKDAY_NAMES = ['MO' => 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday', 'SU' => 'Sunday']

Maps RFC 5545 weekday abbreviations to full weekday names.

The order of the elements matters. Do not change it.

Properties

$by

private array<string|int, mixed> $by = ['bysecond' => ['fmt' => 's', 'type' => 'int', 'is_expansion' => false], 'byminute' => ['fmt' => 'i', 'type' => 'int', 'is_expansion' => false], 'byhour' => ['fmt' => 'H', 'type' => 'int', 'is_expansion' => false], 'byday' => ['fmt' => 'D', 'type' => 'string', 'adjust' => '$current_value = strtoupper(substr($current_value, 0, 2));', 'is_expansion' => false], 'bymonthday' => ['fmt' => 'j', 'type' => 'int', 'is_expansion' => false], 'byyearday' => ['fmt' => 'z', 'type' => 'int', 'adjust' => '$current_value++;', 'is_expansion' => false], 'byweekno' => ['fmt' => 'W', 'type' => 'int', 'is_expansion' => true], 'bymonth' => ['fmt' => 'm', 'type' => 'int', 'is_expansion' => false]]

Info about how to process the various BYxxx rule parts (except BYSETPOS).

As RFC 5545 says:

"BYxxx rule parts modify the recurrence in some manner. BYxxx rule parts for a period of time that is the same or greater than the frequency generally reduce or limit the number of occurrences of the recurrence generated. [...] BYxxx rule parts for a period of time less than the frequency generally increase or expand the number of occurrences of the recurrence."

For more info on these rule parts and how they modify the recurrence, see RFC 5545, §3.3.10.

Note: the order of the elements in this array matters. Do not change it.

$dtstart

private DateTimeInterface $dtstart

Date of the first occurrence of the event.

$exdates

private array<string|int, mixed> $exdates = []

Timestamps of dates to exclude from the recurrence set.

$frequency_interval

private DateInterval $frequency_interval

How far to jump ahead for each main iteration of the recurrence rule.

Derived from $this->rrule->freq and $this->rrule->interval.

$key

private int $key = 0

Iterator key. Points to the current element of $this->occurrences when iterating over an instance of this class.

$limit_after

private DateTimeImmutable $limit_after

Occurrences after this date will not be calculated.

This value is typically one frequency interval after $this->view_end.

$limit_before

private DateTimeImmutable $limit_before

Occurrences before this date will not be calculated.

This value is typically one frequency interval before $this->view_start.

$max_occurrences

private int|float $max_occurrences

Used for sanity checks.

Value may change based on $this->rrule->freq and/or $this->rrule->count.

$occurrences

private array<string|int, mixed> $occurrences = []

Date string records of all valid occurrences.

$rdates

private array<string|int, mixed> $rdates = []

Timestamps of dates to add to the recurrence set. These are dates besides the ones generated from the RRule.

$record_format

private string $record_format = 'Ymd\THis\Z'

\DateTime format to use for the records in $this->occurrences.

$rrule_occurrences

private array<string|int, mixed> $rrule_occurrences = []

Date string records of the initial recurrence set generated from the RRule before any RDates or ExDates are applied.

$type

private int $type

The type of event (normal, floating, or all day), as indicated by one of this class's TYPE_* constants.

$view_end

private DateTimeImmutable $view_end

Occurrences after this date will be skipped when returning results.

$view_start

private DateTimeImmutable $view_start

Occurrences before this date will be skipped when returning results.

Methods

__construct()

Constructor.

public __construct(RRule $rrule, DateTimeInterface $dtstart[, DateInterval|null $view = null ][, DateTimeInterface|null $view_start = null ][, int|null $type = null ][, array<string|int, mixed>|null $rdates = [] ][, array<string|int, mixed>|null $exdates = [] ]) : mixed
Parameters
$rrule : RRule

The recurrence rule for this event.

$dtstart : DateTimeInterface

Date of the event's first occurrence.

$view : DateInterval|null = null

Length of the period for which dates will be shown. For example, use \DateInterval('P1M') to show one month's worth of occurrences, \DateInterval('P1W') to show one week's worth, etc. If null, will be determined automatically.

$view_start : DateTimeInterface|null = null

Lower limit for dates to be shown. Iterating over the object will never return values before this date. If null, will be set to $this->dtstart.

$type : int|null = null

One of this class's TYPE_* constants, or null to set it automatically based on the UNTIL value of the RRule. If this is null and the RRule's UNTIL value is null, default is TYPE_ABSOLUTE.

$rdates : array<string|int, mixed>|null = []

Arbitrary dates to add to the recurrence set. Elements must be arrays containing an instance of \DateTimeInterface and an optional \DateInterval. Used to make exceptions to the general recurrence rule.

$exdates : array<string|int, mixed>|null = []

Dates to exclude from the recurrence set. Elements must be instances of \DateTimeInterface. Used to make exceptions to the general recurrence rule.

add()

Adds an arbitrary date to the recurrence set.

public add(DateTimeInterface $date[, DateInterval|null $duration = null ]) : void

Used for making exceptions to the general recurrence rule. Note that calling this method always rewinds the iterator key.

Parameters
$date : DateTimeInterface

The date to add.

$duration : DateInterval|null = null

Optional duration for this occurrence. Only necessary if the duration for this occurrence differs from the usual duration of the event.

calculateWeekNum()

Calculates the week number of a date according to RFC 5545.

public static calculateWeekNum(DateTimeInterface $current, string $wkst) : int
Parameters
$current : DateTimeInterface
$wkst : string
Return values
int

current()

Returns a \DateTimeInterface object for the currently selected element in the event's recurrence set.

public current() : DateTimeInterface|false

If $this->type is self::TYPE_FLOATING or self::TYPE_ALLDAY, the returned object will be a mutable \DateTime instance so that its time zone can be changed to the viewing user's current time zone.

Otherwise, the returned object will a \DateTimeImmutable instance.

Return values
DateTimeInterface|false

The date of the occurrence, or false on error.

dateOccurs()

Checks whether the given date/time occurs in the recurrence set.

public dateOccurs(DateTimeInterface $date) : bool
Parameters
$date : DateTimeInterface

A date.

Return values
bool

Whether the date occurs in the recurrence set.

getDtStart()

Returns a copy of $this->dtstart.

public getDtStart() : DateTimeInterface
Return values
DateTimeInterface

getExDates()

Returns a copy of $this->exdates.

public getExDates() : array<string|int, mixed>
Return values
array<string|int, mixed>

getFrequencyInterval()

Returns a copy of $this->frequency_interval.

public getFrequencyInterval() : DateInterval
Return values
DateInterval

getNext()

Moves the iterator key one step forward, and then returns a DateTimeInterface object for the newly selected element in the event's recurrence set.

public getNext() : DateTimeInterface|false
Return values
DateTimeInterface|false

The next occurrence, or false if there are no more occurrences.

getPrev()

Moves the iterator key one step backward, and then returns a DateTimeInterface object for the newly selected element in the event's recurrence set.

public getPrev() : DateTimeInterface|false
Return values
DateTimeInterface|false

The previous occurrence, or false if there is no previous occurrence.

getRDates()

Returns a copy of $this->rdates.

public getRDates() : array<string|int, mixed>
Return values
array<string|int, mixed>

getRRuleOccurrences()

Returns occurrences generated by the RRule only.

public getRRuleOccurrences() : array<string|int, mixed>
Return values
array<string|int, mixed>

key()

Get the current value of the iterator key.

public key() : int
Return values
int

The current value of the iterator key.

remove()

Removes a date from the recurrence set.

public remove(DateTimeInterface $date) : void

Used for making exceptions to the general recurrence rule. Note that calling this method always rewinds the iterator key.

Parameters
$date : DateTimeInterface

The date to remove.

Finds the iterator key that corresponds to the requested value.

public search(string $needle) : int|false
Parameters
$needle : string

The value to search for.

Return values
int|false

The key for the requested value, or false on error.

setKey()

Moves the iterator key to a specific position.

public setKey(int $key) : int

If the requested key is invalid, will go to the closest valid one.

Parameters
$key : int
Return values
int

The new value of the iterator key.

valid()

Checks whether the current value of the iterator key is valid.

public valid() : bool
Return values
bool

Whether the current value of the iterator key is valid.

calculate()

Calculates occurrences based on the recurrence rule.

private calculate() : void

expand()

Finds additional occurrences based on any BYxxx rule parts in the RRule.

private expand(DateTime $current[, string $break_after = null ]) : Generator<string|int, DateTimeImmutable>

Expansions are occurrences that happen inside one iteration of the RRule's stated frequency. For example, if the frequency is set to HOURLY, that normally means that the event recurs on minute 0 of every hour (or whatever minute was set in DTSTART). But if the RRule's BYMINUTE property is set to '0,30', then the occurrences are expanded so that the event recurs at minute 0 and minute 30 of every hour.

Parameters
$current : DateTime

An occurrence of the event to expand.

$break_after : string = null

Name of a $this->by element. Used during recursive calls to this method.

Return values
Generator<string|int, DateTimeImmutable>

expandMonthByDay()

Used when expanding an occurrence that is part of a monthly recurrence set that has a byday rule, or part of a yearly recurrence set that has both a bymonth rule and a byday rule.

private expandMonthByDay(DateTime $current, array<string|int, mixed> $expansion_values, string $current_value) : Generator<string|int, DateTimeImmutable>
Parameters
$current : DateTime

An occurrence of the event to expand.

$expansion_values : array<string|int, mixed>

Values from the byday rule.

$current_value : string
Return values
Generator<string|int, DateTimeImmutable>

expandYearByDay()

Used when expanding an occurrence that is part of a yearly recurrence set that has a byday rule but not a bymonth rule.

private expandYearByDay(DateTime $current, array<string|int, mixed> $expansion_values, string $current_value) : Generator<string|int, DateTimeImmutable>
Parameters
$current : DateTime

An occurrence of the event to expand.

$expansion_values : array<string|int, mixed>

Values from the byday rule.

$current_value : string
Return values
Generator<string|int, DateTimeImmutable>

jumpToVisible()

If possible, move $current ahead in order to skip values before $this->view_start.

private jumpToVisible(DateTime &$current) : void
Parameters
$current : DateTime

limit()

Checks whether a calculated occurrence should be included based on BYxxx rule parts in the RRule.

private limit(DateTime $current) : bool

Limitations cause occurrences that would normally occur according the RRule's stated frequency to be skipped. For example, if the frequency is set to HOURLY, that normally means that the event recurs on minute 0 of every hour (or whatever minute was set in DTSTART) of every day. But if the BYDAY rule part is set to 'TU,TH', then occurrences are limited so that the event recurs only at every hour during Tuesdays and Thursdays. Occurrences that happen on any other day of the week are skipped.

Parameters
$current : DateTime

A occurrence whose value we want to check.

Return values
bool

Whether the occurrence is allowed.

limitBySetPos()

Applies BYSETPOS limitation to the reccurrence set.

private limitBySetPos() : void

nextInterval()

Move $current ahead to the next interval.

private nextInterval(DateTime &$current) : void

Handles months of varying lengths according to RFC 5545's rules.

Parameters
$current : DateTime

record()

Adds an occurrence to $this->occurrences.

private record(DateTimeInterface $occurrence) : bool
Parameters
$occurrence : DateTimeInterface
Return values
bool

True if the occurrence is a new addition; false if it is a duplicate or out of bounds.

setFrequencyInterval()

Sets the value of $this->frequency_interval.

private setFrequencyInterval() : void

sortWeekdays()

Sorts an array of weekday abbreviations so that $this->rrule->wkst is always the first item.

private sortWeekdays(array<string|int, mixed> $weekdays) : array<string|int, mixed>
Parameters
$weekdays : array<string|int, mixed>

An array of weekday abbreviations.

Return values
array<string|int, mixed>

Sorted version of $weekdays.


        
On this page

Search results