{"id":17679453,"url":"https://github.com/jonaswanke/rrule","last_synced_at":"2026-01-06T17:22:37.416Z","repository":{"id":37098729,"uuid":"265180741","full_name":"JonasWanke/rrule","owner":"JonasWanke","description":"🔁 Recurrence rule parsing \u0026 calculation as defined in the iCalendar RFC","archived":false,"fork":false,"pushed_at":"2025-01-06T09:24:41.000Z","size":398,"stargazers_count":54,"open_issues_count":13,"forks_count":24,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-30T02:05:43.795Z","etag":null,"topics":["dart","hacktoberfest","ical","icalendar","package","recurrence","recurrence-rules","recurrent-event","rrule"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/rrule","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JonasWanke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"JonasWanke"}},"created_at":"2020-05-19T07:48:14.000Z","updated_at":"2025-03-02T07:50:59.000Z","dependencies_parsed_at":"2023-02-14T00:46:20.584Z","dependency_job_id":"5e8d3ad0-702f-477e-a4eb-c9295c06f905","html_url":"https://github.com/JonasWanke/rrule","commit_stats":{"total_commits":168,"total_committers":7,"mean_commits":24.0,"dds":0.1071428571428571,"last_synced_commit":"81be667b722eaa5ac7e9d608e4d45e527a8a5b30"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonasWanke%2Frrule","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonasWanke%2Frrule/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonasWanke%2Frrule/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JonasWanke%2Frrule/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JonasWanke","download_url":"https://codeload.github.com/JonasWanke/rrule/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247427006,"owners_count":20937201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","hacktoberfest","ical","icalendar","package","recurrence","recurrence-rules","recurrent-event","rrule"],"created_at":"2024-10-24T08:42:01.718Z","updated_at":"2026-01-06T17:22:37.384Z","avatar_url":"https://github.com/JonasWanke.png","language":"Dart","funding_links":["https://github.com/sponsors/JonasWanke"],"categories":[],"sub_categories":[],"readme":"🔁 Recurrence rule parsing \u0026 calculation as defined in the iCalendar RFC\n\n![Build, Test \u0026 Lint](https://github.com/JonasWanke/rrule/workflows/Build,%20Test%20\u0026%20Lint/badge.svg)\n[![Coverage](https://codecov.io/gh/JonasWanke/rrule/branch/main/graph/badge.svg)](https://codecov.io/gh/JonasWanke/rrule)\n\n## How to use this package\n\nCreate a [`RecurrenceRule`]:\n\n```dart\n// Every two weeks on Tuesday and Thursday, but only in December.\nfinal rrule = RecurrenceRule(\n  frequency: Frequency.weekly,\n  interval: 2,\n  byWeekDays: {\n    ByWeekDayEntry(DateTime.tuesday),\n    ByWeekDayEntry(DateTime.thursday),\n  },\n  byMonths: {12},\n);\n```\n\nAnd get its recurrences by evaluating it from a start date:\n\n```dart\nfinal Iterable\u003cDateTime\u003e instances = rrule.getInstances(\n  start: DateTime.now().copyWith(isUtc: true),\n);\n```\n\n\u003e ⚠️ \u003ckbd\u003errule\u003c/kbd\u003e doesn't care about any time-zone-related stuff.\n\u003e All supplied `DateTime`s must have `isUtc` set to `true` (because UTC doesn't have complications like summer and winter time), but the actual time zone is then ignored, e.g., when generating human-readable text.\n\u003e\n\u003e If you have a `DateTime` instance in the local time zone, you can use \u003ckbd\u003errule\u003c/kbd\u003e's helper `dateTime.copyWith(isUtc: true)` which keeps the date and time but sets `isUtc` to true.\n\u003e To convert the generated instances back to your local time zone, you can use `dateTime.copyWith(isUtc: false)`.\n\nTo limit returned instances (besides using `RecurrenceRule.until` or `RecurrenceRule.count`), you can use Dart's default `Iterable` functions:\n\n```dart\nfinal firstThreeInstances = instances.take(3);\n\nfinal onlyThisYear = instances.takeWhile(\n  (instance) =\u003e instance.year == DateTime.now().year,\n);\n\nfinal startingNextYear = instances.where(\n  (instance) =\u003e instance.year \u003e DateTime.now().year,\n);\n```\n\n## Machine-readable String conversion\n\nYou can convert between [`RecurrenceRule`]s and [iCalendar/RFC 5545][RFC 5545]-compliant `String`s by using [`RecurrenceRuleStringCodec`] or the following convenience methods:\n\n```dart\nfinal string = 'RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;BYMONTH=12';\nfinal rrule = RecurrenceRule.fromString(string);\n\nassert(rrule.toString() == string); // true\n```\n\n\u003csup\u003e(Same RRULE as the first one)\u003c/sup\u003e\n\n## Human-readable Text conversion\n\nYou can convert a [`RecurrenceRule`] to a human-readable `String`s by using [`RecurrenceRule.toText()`]:\n\n```dart\n// First, load the localizations (currently, only English and Dutch are\n// supported):\nfinal l10n = await RruleL10nEn.create();\n\nfinal rrule = RecurrenceRule.fromString(\n  'RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;BYMONTH=12',\n);\n\nfinal text = 'Every other week in December on Tuesday \u0026 Thursday';\nassert(rrule.toText(l10n: l10n) == string); // true\n```\n\n\u003csup\u003e(Same RRULE as the first one)\u003c/sup\u003e\n\nA few more examples:\n\n- `RRULE:INTERVAL=4;FREQ=HOURLY`: Every 4 hours\n- `RRULE:FREQ=DAILY;BYSETPOS=1,-2;BYMONTH=1,12;BYMONTHDAY=1,-1`: Daily in January \u0026 December on the 1st \u0026 2nd-to-last instance of the 1st \u0026 last day of the month\n- `RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR`: Weekly on weekdays\n- `RRULE:INTERVAL=2;FREQ=WEEKLY`: Every other week\n- `RRULE:FREQ=MONTHLY;BYDAY=-3TU`: Monthly on the 3rd-to-last Tuesday\n- `RRULE:FREQ=YEARLY;BYDAY=+13FR`: Annually on the 13th Friday of the year\n- `RRULE:FREQ=YEARLY;BYSETPOS=1,-2;BYMONTH=1,12;BYWEEKNO=1,-1;BYYEARDAY=1,-1;BYMONTHDAY=1,-1;BYDAY=MO,WE`: Annually on the 1st \u0026 2nd-to-last instance of every Monday \u0026 Wednesday that are also the 1st or last day of the month, that are also the 1st or last day of the year, that are also in the 1st or last week of the year, and that are also in January or December\n\nWhile this already supports really complex RRULEs, some of them are not (yet) supported. See [`RecurrenceRule.canFullyConvertToText`] for more information.\n\n## JSON conversion\n\nYou can convert between [`RecurrenceRule`]s and [jCal/RFC 7265][RFC 7265]-compliant JSON using the following convenience methods:\n\n```dart\nfinal json = \u003cString, dynamic\u003e{\n  'freq': 'WEEKLY',\n  'interval': 2,\n  'byday': ['TU', 'TH'],\n  'bymonth': [12],\n};\nfinal rrule = RecurrenceRule.fromJson(json);\n\nexpect(rrule.toJson(), json);\n```\n\n\u003csup\u003e(Same RRULE as the first one)\u003c/sup\u003e\n\n## Limitations\n\n- custom week starts are not supported (`WKST` in the specification) – Monday is the only valid value (encoded as `MO`)\n- leap seconds are not supported (limitation of Dart's `DateTime`)\n- only years 0–9999 in the Common Era are supported (limitation of the iCalendar RFC, but if you have a use case, this should be easy to extend)\n\n## Thanks\n\nThe recurrence calculation code of `RecurrencRule`s is mostly a partial port of [\u003ckbd\u003errule.js\u003c/kbd\u003e], though with a lot of modifications to use Dart's `DateTime` and not having to do date/time calculations manually. You can find the license of [\u003ckbd\u003errule.js\u003c/kbd\u003e] in the file `LICENSE-rrule.js.txt`.\n\n[\u003ckbd\u003errule.js\u003c/kbd\u003e]: https://github.com/jakubroztocil/rrule\n[RFC 5545]: https://datatracker.ietf.org/doc/html/rfc5545\n[RFC 7265]: https://datatracker.ietf.org/doc/html/rfc7265\n[`RecurrenceRule`]: https://pub.dev/documentation/rrule/latest/rrule/RecurrenceRule-class.html\n[`RecurrenceRule.canFullyConvertToText`]: https://pub.dev/documentation/rrule/latest/rrule/RecurrenceRule/canFullyConvertToText.html\n[`RecurrenceRule.toText()`]: https://pub.dev/documentation/rrule/latest/rrule/RecurrenceRule/toText.html\n[`RecurrenceRuleStringCodec`]: https://pub.dev/documentation/rrule/latest/rrule/RecurrenceRuleStringCodec-class.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonaswanke%2Frrule","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonaswanke%2Frrule","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonaswanke%2Frrule/lists"}