php-rrule

repository·master·Indexed 20 days ago

https://github.com/rlanvin/php-rrule

A 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.

Tokens
3.4K
Snippets
16
Records
18
Agent score
72%

What's inside php-rrule

  1. Manage recurrence sets with RSet

    master

    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:

    • Combine multiple RRule instances into one set.
    • Add specific dates that should always occur (addDate).
    • Add specific dates or rules that should be excluded (addExDate, addExRule).
    • Parse an entire RFC-compliant recurrence string directly in the constructor.
    • Retrieve occurrences as an array of \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 5
  2. Basic usage of the RRule class

    master

    You 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:

    • PHP >= 7.3
    • The 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 times
  3. Determine if an RRule is finite or infinite

    master

    Use 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
    }
  4. Create an RRule or RSet from an RFC string

    master

    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');
  5. Generate human-readable descriptions of an RRule

    master

    The humanReadable() method converts an RRule instance into a natural language string (e.g., "Every Monday").

    Requirements:

    • The 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:

    NameTypeDescription
    use_intlboolUse the intl extension or not (autodetect if omitted).
    localestringThe locale to use (e.g., en_US, fr_FR). Autodetects if omitted.
    fallbackstringFallback locale if the primary locale is not found (default: en).
    date_formattercallableA custom function used to format the date. It must accept a DateTime object and return a string.
    explicit_infiniteboolIf true, mentions "forever" if the rule has no end date.
    dtstartboolIf true, mentions the start date in the description.
    include_startboolWhether to include the start date.
    start_time_onlyboolIf true, mentions only the time of day, omitting the date.
    include_untilboolWhether to include the end date (UNTIL) in the description.
    custom_pathstringPath to custom translation files.
    // Example usage of humanReadable
    $rrule = new RRule([...]);
    $description = $rrule->humanReadable([
        'locale' => 'fr_FR',
        'explicit_infinite' => true,
        'include_until' => true
    ]);
  6. Convert an RRule to an RFC 5545 string

    master

    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;
  7. Retrieve occurrences from an RSet

    master

    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.
    • Iteration: Since 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')) {
        // ...
    }
  8. Initialize RSet from an RFC string

    master

    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);
  9. Get the total number of occurrences

    master

    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
    }
  10. Check if an RSet is finite or infinite

    master

    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.