From 1f65571bbf491b4ca98da719fe2f56bc9264c753 Mon Sep 17 00:00:00 2001 From: mampfes Date: Sat, 12 Feb 2022 10:09:40 +0100 Subject: [PATCH] use icalevents instead of icalendar + recurring_ical_events The icalevents python package is much more lightweight than icalendar + recurring_ical_events. recurring_ical_events also problems in some environments, see github issue: https://github.com/mampfes/hacs_waste_collection_schedule/issues/164 --- .../waste_collection_schedule/manifest.json | 4 +- .../waste_collection_schedule/service/ICS.py | 61 ++++++++----------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/custom_components/waste_collection_schedule/manifest.json b/custom_components/waste_collection_schedule/manifest.json index b01e6530d..cf9641223 100644 --- a/custom_components/waste_collection_schedule/manifest.json +++ b/custom_components/waste_collection_schedule/manifest.json @@ -2,9 +2,9 @@ "domain": "waste_collection_schedule", "name": "waste_collection_schedule", "documentation": "https://github.com/mampfes/hacs_waste_collection_schedule#readme", - "requirements": ["icalendar", "recurring_ical_events", "bs4"], + "requirements": ["icalevents", "bs4"], "dependencies": [], "codeowners": ["@mampfes"], "iot_class": "cloud_polling", - "version": "1.14.0" + "version": "1.16.0-pre2" } diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py index 60f5411ec..0aec6e9d5 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py @@ -2,8 +2,7 @@ import logging import re -import icalendar -import recurring_ical_events +from icalevents import icalevents _LOGGER = logging.getLogger(__name__) @@ -17,14 +16,6 @@ def __init__(self, offset=None, regex=None, split_at=None): self._split_at = split_at def convert(self, ics_data): - # parse ics file - try: - calendar = icalendar.Calendar.from_ical(ics_data) - except Exception as err: - _LOGGER.error(f"Parsing ics data failed:{str(err)}") - _LOGGER.debug(ics_data) - return [] - # calculate start- and end-date for recurring events start_date = datetime.datetime.now().replace( hour=0, minute=0, second=0, microsecond=0 @@ -33,32 +24,34 @@ def convert(self, ics_data): start_date -= datetime.timedelta(days=self._offset) end_date = start_date.replace(year=start_date.year + 1) - events = recurring_ical_events.of(calendar).between(start_date, end_date) + # parse ics data + events = icalevents.events( + start=start_date, end=end_date, string_content=ics_data.encode() + ) entries = [] for e in events: - if e.name == "VEVENT": - # calculate date - dtstart = None - if type(e.get("dtstart").dt) == datetime.date: - dtstart = e.get("dtstart").dt - elif type(e.get("dtstart").dt) == datetime.datetime: - dtstart = e.get("dtstart").dt.date() - if self._offset is not None: - dtstart += datetime.timedelta(days=self._offset) - - # calculate waste type - summary = str(e.get("summary")) - if self._regex is not None: - match = self._regex.match(summary) - if match: - summary = match.group(1) - - if self._split_at is not None: - summary = re.split(self._split_at, summary) - for t in summary: - entries.append((dtstart, t.strip().title())) - else: - entries.append((dtstart, summary)) + # calculate date + dtstart = None + if type(e.start) == datetime.date: + dtstart = e.start + elif type(e.start) == datetime.datetime: + dtstart = e.start.date() + if self._offset is not None: + dtstart += datetime.timedelta(days=self._offset) + + # calculate waste type + summary = str(e.summary) + if self._regex is not None: + match = self._regex.match(summary) + if match: + summary = match.group(1) + + if self._split_at is not None: + summary = re.split(self._split_at, summary) + for t in summary: + entries.append((dtstart, t.strip().title())) + else: + entries.append((dtstart, summary)) return entries