php-rrule: recurrence rules for PHP without the calendar plumbing
Lightweight and fast recurring dates library for PHP (RFC 5545)
At a glance
- What is it?
- php-rrule is a PHP port of the python-dateutil recurrence implementation, built to be stricter about RFC 5545 than the Python original, and it turns an RRULE string or array into a list of dates you can iterate directly.
- Who is it for?
- php-rrule fits a PHP developer who has to compute repeating dates, whether for a calendar, a billing cycle or a scheduled report, and who would rather depend on a small library than build the date arithmetic by hand, since the RFC 5545 corner cases are the part nobody enjoys.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A port of python-dateutil, with the author's commentary added
php-rrule started as a port of python-dateutil, and the project says plainly why: the author was not happy with the existing PHP implementations and thought it would be a good learning project. That origin explains both the design and the tone of the source. The stated difficulty with the Python original is that the algorithms are not commented and the variables are very opaque, and the author tried to comment and explain as much of the algorithm as possible in the PHP port, inviting readers to check the code if they are interested. For a reader evaluating the library, that is a meaningful difference from the original. Recurrence logic is the kind of code you end up reading when a date comes out wrong, and here the reasoning is meant to be legible rather than something you have to reverse engineer.
Constructing a rule from an array and iterating the dates
The basic example builds a rule from an associative array of rule parts and then iterates it directly, which is the shape most of your code will take. Here is the monthly rule from the project overview.
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 2015Two things stand out. The rule parts use the RFC names, FREQ, INTERVAL, DTSTART and COUNT, so a rule you have seen in an iCalendar file reads the same here. And the object is iterable, yielding DateTime instances, which means you do not need to call a method to get the list and then loop over an array. The output comment shows the actual dates the example produces, starting on the first of the month and running six times.
humanReadable turns a rule into a sentence
Every rule can also be rendered as a sentence, which is the feature that turns a recurrence rule into something a user interface can show.
echo $rrule->humanReadable(),"\n";
// monthly on the 1st of the month, starting from 01/06/2015, 6 timesThe output describes the schedule in the same terms a person would use, including the start date and the number of occurrences. It also means the rule is not locked inside your database as an opaque string, since a settings screen can show the user what they have actually set up. The catch is that this method leans on the intl extension, which the requirements list as recommended but not strictly required, so on a host without it you lose the sentence but keep the dates.
Composer install and the autoloader
Installation is the standard Composer path, and the project recommends it that way. One command, composer require rlanvin/php-rrule, adds the library to your composer.json and installs it. Then the autoloader gives you access to the library.
require 'vendor/autoload.php';The requirements are PHP 7.3 or newer, plus the intl extension if you want humanReadable output. There is also a phpunit.xml.dist at the repository root for the test configuration, a CHANGELOG.md, and a src/ and tests/ layout that follows the usual PHP library structure, with the scripts in bin/ rather than in the package root.
Stricter than python-dateutil about the RFC
The one behavioural difference the project calls out is the important one, and it is worth reading before you commit. The library differs from the Python version in various aspects, notably in the respect of the RFC: this version is a bit stricter and will not accept many non-compliant combinations of rule parts that the Python version otherwise accepts. There are also some additional features in this version, so the relationship is not simply stricter, but stricter is the axis that can break your integration. If your rules come from user input, from a third party calendar system, or from years of stored strings, some of them may be combinations that a permissive parser tolerates and this one rejects. That is a deliberate choice, and it does produce cleaner behaviour on rules that are actually malformed, but it means you should plan for an exception path when reading rules from outside your own system.
Translation tooling for a library that reads like a sentence
Because humanReadable output is a sentence, the library carries a translation review tool, and the project documents two ways to use it. The first prints a list of examples using the locale you name, with English as the default, by running ./bin/review_translations.php with the --locale option. The second tests a specific rule across all available locales, by running the same script with the --rule option, which is what you would use when a phrase has just been changed. This is a small detail that says something about the project's maturity. Most recurrence libraries stop at the date arithmetic, and the human-readable layer is usually where internationalisation quietly falls apart, with terms like every other week or on the first Monday rendered in English regardless of the locale. Having a review script for the rendered sentences is an admission that this layer needs checking, and a way to check it.
Version 3 is a deliberate step, and the changelog is where it shows
The release history shows a big version jump. The tags are v3.0.0 on 2026-07-29, v2.6.0 on 2025-05-05 and v2.5.2 on 2025-02-21, so the project spent most of its life in the 2.x line and then made a clean break, which in a library like this usually means a deliberate decision about the public API rather than an accident. The last push to the repository was on 2026-07-29, the same moment as the v3.0.0 tag, and the project is not archived. The documentation itself lives in the wiki rather than in the repository, and the project points at RFC 5545 section 3.3.10 for the specification of the rule format, so the authoritative source for what a rule means is the RFC, not the library docs. The coding style note in the project is PSR-2 with tabs, which is a small thing but tells you what a pull request should look like before you write one.
Where php-rrule is the wrong tool
Two situations call for something else. The first is a schedule that is not expressible as a recurrence rule. A rule describes a repeating pattern with a period, a frequency and optional filters. A job that runs every fifteen minutes on weekdays except the last Friday of the quarter, or one that depends on the previous run's outcome, is not a rule, and a recurrence library will not help you model it. The second is a project already committed to a full calendar library that includes recurrence handling along with events, attendees, alarms and serialisation. Adding a second source of truth for dates in a PHP codebase is a maintenance decision rather than a technical one. The library also does not handle the surrounding problems of calendars, such as storing events, and its licence is stated in the project overview as the MIT License, with the licence text in the LICENSE file at the repository root, which is the permissive option you would want for a dependency like this.
Editorial conclusion
php-rrule fits a PHP developer who has to compute repeating dates, whether for a calendar, a billing cycle or a scheduled report, and who would rather depend on a small library than build the date arithmetic by hand, since the RFC 5545 corner cases are the part nobody enjoys. It does not fit a project that needs to accept the loosest possible rule strings, because the project states that this port is stricter than the Python original and will not accept many non-compliant combinations that python-dateutil otherwise accepts, and a parser that rejects input another library tolerates is a real interoperability cost. Before you adopt it, check that the intl extension is present if you want humanReadable output, keep your requirement on PHP 7.3 or newer, and read the CHANGELOG.md, since the version moved from 2.x to v3.0.0 on 2026-07-29 and the RFC strictness means a rule that parsed under v2 may not under v3.
Frequently asked questions
How do I install php-rrule and use it?
Install it with Composer using composer require rlanvin/php-rrule, then require 'vendor/autoload.php' and build a rule with new RRule([...]). The library needs PHP 7.3 or newer, and the intl extension is recommended for humanReadable().
How does php-rrule differ from python-dateutil?
It was started as a port of python-dateutil, with more of the algorithm commented and explained. The stated difference is that this version is stricter about RFC 5545 and will not accept many non-compliant combinations of rule parts that the Python version otherwise accepts, and it also adds some features.
What does humanReadable() do in php-rrule?
It renders the rule as a sentence, for example monthly on the 1st of the month, starting from 01/06/2015, 6 times. It relies on the intl extension, which is recommended but not strictly required.
Which PHP versions does php-rrule support and how recent is it?
PHP 7.3 or newer is required. The tags are v3.0.0 from 2026-07-29, v2.6.0 from 2025-05-05 and v2.5.2 from 2025-02-21, and the last push to the repository was on 2026-07-29.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rlanvin-php-rrule)Was this useful?