Install php-rrule via Composer
masterThe recommended way to install the library is through Composer. Run the following command to add it to your composer.json and install the dependencies.
composer require rlanvin/php-rrulerepository·master·Indexed 20 days ago
https://github.com/rlanvin/php-rruleA lightweight and fast PHP implementation of RFC 5545 recurrence rules (RRULE), originally ported from python-dateutil. It provides the RRule class for calculating recurring dates and the RSet class for managing complex sets of rules, including inclusions (RDATE) and exclusions (EXRULE, EXDATE). Features include RFC 5545 string export/import, human-readable descriptions via the intl extension, and memory-efficient iteration over occurrences. Requires PHP >= 7.3.
The recommended way to install the library is through Composer. Run the following command to add it to your composer.json and install the dependencies.
composer require rlanvin/php-rruleAfter installation, include the Composer autoloader to access the RRule\RRule class.
require 'vendor/autoload.php';The RSet class allows you to manage a complex set of recurrence rules (RRULEs), specific dates to include (RDATEs), and rules or dates to exclude (EXRULEs and EXDATEs). It implements RRuleInterface, meaning it can be treated as a single recurrence rule, and it is iterable, allowing you to loop through all resulting occurrences.
Key capabilities:
RRule instances into one set.addDate).addExDate, addExRule).\DateTime objects or iterate over them directly.use RRule\RSet;
// Create an RSet from an RFC string
$rset = new RSet("DTSTART:20230101T000000Z\nRRULE:FREQ=DAILY;COUNT=10");
// Or build it manually
$rset = new RSet();
$rset->addRRule('FREQ=WEEKLY;BYDAY=MO');
$rset->addDate('2023-05-01'); // Force this date to occur
$rset->addExDate('2023-05-08'); // Exclude this specific date
// Get occurrences
$occurrences = $rset->getOccurrences(5); // Get first 5You can instantiate an RRule object by passing an array of RFC 5545 recurrence rule parts. The object is iterable, allowing you to loop through occurrences, and provides a humanReadable() method for a natural language description of the rule.
Requirements:
intl extension is recommended for the humanReadable() method to work correctly.use RRule\RRule;
$rrule = new RRule([
'FREQ' => 'MONTHLY',
'INTERVAL' => 1,
'DTSTART' => '2015-06-01',
'COUNT' => 6
]);
foreach ($rrule as $occurrence) {
echo $occurrence->format('D d M Y'),", ";
}
// Mon 01 Jun 2015, Wed 01 Jul 2015, Sat 01 Aug 2015, Tue 01 Sep 2015, Thu 01 Oct 2015, Sun 01 Nov 2015
echo $rrule->humanReadable(),"\n";
// monthly on the 1st of the month, starting from 01/06/2015, 6 timesUse these methods to check the termination conditions of a rule:
isFinite(): Returns true if the rule has an end condition (COUNT or UNTIL).isInfinite(): Returns true if the rule has no end condition.if ($rrule->isInfinite()) {
// Handle infinite recurrence
}The static method createFromRfcString($string, $force_rset = false) is the recommended way to instantiate a rule from a string. It automatically detects whether the string represents a single RRule or an RSet (a collection of rules/dates). If $force_rset is set to true, it will always return an RSet object.
use RRule\RRule;
$rrule = RRule::createFromRfcString('FREQ=DAILY;INTERVAL=1');The humanReadable() method converts an RRule instance into a natural language string (e.g., "Every Monday").
Requirements:
intl PHP extension is highly recommended for better localization and date formatting. If not available, the library falls back to standard PHP date formatting.Available Options:
| Name | Type | Description |
|---|---|---|
use_intl | bool | Use the intl extension or not (autodetect if omitted). |
locale | string | The locale to use (e.g., en_US, fr_FR). Autodetects if omitted. |
fallback | string | Fallback locale if the primary locale is not found (default: en). |
date_formatter | callable | A custom function used to format the date. It must accept a DateTime object and return a string. |
explicit_infinite | bool | If true, mentions "forever" if the rule has no end date. |
dtstart | bool | If true, mentions the start date in the description. |
include_start | bool | Whether to include the start date. |
start_time_only | bool | If true, mentions only the time of day, omitting the date. |
include_until | bool | Whether to include the end date (UNTIL) in the description. |
custom_path | string | Path to custom translation files. |
// Example usage of humanReadable
$rrule = new RRule([...]);
$description = $rrule->humanReadable([
'locale' => 'fr_FR',
'explicit_infinite' => true,
'include_until' => true
]);Use the rfcString() method to export the current rule as a standard RFC 5545 string. You can optionally pass a boolean $include_timezone (defaults to true) to determine whether to include timezone identifiers on DTSTART and UNTIL.
$rfcString = $rrule->rfcString();
// or
$rfcString = (string) $rrule;To get the actual dates generated by the recurrence set, use getOccurrences() or iterate over the object directly.
getOccurrences($limit = null): Returns an array of \DateTime objects. If $limit is provided, it returns up to $n$ occurrences. If the set is infinite and no limit is provided, it throws a \LogicException.RSet implements Iterator, you can use it directly in a foreach loop.occursAt($date): Returns true if the provided date is part of the recurrence set, taking into account all inclusions and exclusions.// Using getOccurrences
$dates = $rset->getOccurrences(10);
// Using foreach
foreach ($rset as $date) {
echo $date->format('Y-m-d') . PHP_EOL;
}
// Checking a specific date
if ($rset->occursAt('2023-01-01')) {
// ...
}You can instantiate an RSet by passing a single RFC-compliant text block to the constructor. The parser supports DTSTART, RRULE, EXRULE, RDATE, and EXDATE properties. Each property must be followed by a colon (:).
If multiple DTSTART properties are found in the string, an \InvalidArgumentException is thrown.
$rfcString = "DTSTART:20230101T000000Z\nRRULE:FREQ=MONTHLY;BYDAY=1SU\nEXDATE:20230205T000000Z";
$rset = new RRule\RSet($rfcString);The count() method returns the total number of occurrences in the rule.
Warning: Calling count() on an infinite rule will throw a \LogicException. For finite rules, this method may incur a performance penalty as it may need to iterate through the entire recurrence to calculate the total.
try {
$total = $rrule->count();
} catch (\LogicException $e) {
// Rule is infinite
}An RSet is considered infinite if any of its constituent RRULEs are infinite.
isInfinite(): Returns true if the set has no end condition.isFinite(): Returns true if the set has an end condition.count(): Returns the total number of occurrences. Warning: Calling count() on an infinite set will throw a \LogicException. For finite sets, this may incur a performance penalty if the total hasn't been cached yet.