mirror of
https://github.com/Kozea/Radicale.git
synced 2025-09-15 20:36:55 +00:00
(#1812) Processing exdates. Duration handling. Return empty element if
all events was filtered Author: Georgiy <metallerok@gmail.com>
This commit is contained in:
parent
02be6419ae
commit
2a304259fe
1 changed files with 35 additions and 21 deletions
|
@ -358,15 +358,29 @@ def _expand(
|
||||||
if hasattr(vevent_recurrence, "dtend"):
|
if hasattr(vevent_recurrence, "dtend"):
|
||||||
duration = vevent_recurrence.dtend.value - vevent_recurrence.dtstart.value
|
duration = vevent_recurrence.dtend.value - vevent_recurrence.dtstart.value
|
||||||
elif hasattr(vevent_recurrence, "duration"):
|
elif hasattr(vevent_recurrence, "duration"):
|
||||||
|
try:
|
||||||
duration = vevent_recurrence.duration.value
|
duration = vevent_recurrence.duration.value
|
||||||
|
if duration.total_seconds() <= 0:
|
||||||
|
logger.warning("Invalid DURATION: %s", duration)
|
||||||
|
duration = None
|
||||||
|
except (AttributeError, TypeError) as e:
|
||||||
|
logger.warning("Failed to parse DURATION: %s", e)
|
||||||
|
duration = None
|
||||||
|
|
||||||
# Generate EXDATE to remove from expansion range
|
# Generate EXDATE to remove from expansion range
|
||||||
|
exdates_set = {}
|
||||||
if hasattr(vevent_recurrence, 'exdate'):
|
if hasattr(vevent_recurrence, 'exdate'):
|
||||||
exdates = vevent_recurrence.exdate.value
|
exdates = vevent_recurrence.exdate.value
|
||||||
if not isinstance(exdates, list):
|
if not isinstance(exdates, list):
|
||||||
exdates = [exdates]
|
exdates = [exdates]
|
||||||
logger.debug("EXDATE values: %s", exdates)
|
|
||||||
# TODO: these exdate values are not removed from the expanded set
|
exdates_set = {
|
||||||
|
exdate.astimezone(datetime.timezone.utc) if isinstance(exdate, datetime.datetime)
|
||||||
|
else datetime.datetime.fromordinal(exdate.toordinal()).replace(tzinfo=None)
|
||||||
|
for exdate in exdates
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("EXDATE values: %s", exdates_set)
|
||||||
|
|
||||||
rruleset = None
|
rruleset = None
|
||||||
if hasattr(vevent_recurrence, 'rrule'):
|
if hasattr(vevent_recurrence, 'rrule'):
|
||||||
|
@ -385,8 +399,7 @@ def _expand(
|
||||||
# the event. If this introduces an extra reccurence point then
|
# the event. If this introduces an extra reccurence point then
|
||||||
# that event should be included as it is still ongoing. If no
|
# that event should be included as it is still ongoing. If no
|
||||||
# extra point is generated then it was a no-op.
|
# extra point is generated then it was a no-op.
|
||||||
|
rstart = start - duration if duration and duration.total_seconds() > 0 else start
|
||||||
rstart = start - duration if duration else start
|
|
||||||
recurrences = rruleset.between(rstart, end, inc=True)
|
recurrences = rruleset.between(rstart, end, inc=True)
|
||||||
|
|
||||||
_strip_component(vevent_component)
|
_strip_component(vevent_component)
|
||||||
|
@ -407,7 +420,10 @@ def _expand(
|
||||||
logger.debug("Recurrence %s filtered out by time-range", recurrence_utc)
|
logger.debug("Recurrence %s filtered out by time-range", recurrence_utc)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check here for exdate
|
# Check exdate
|
||||||
|
if recurrence_utc in exdates_set:
|
||||||
|
logger.debug("Recurrence %s excluded by EXDATE", recurrence_utc)
|
||||||
|
continue
|
||||||
|
|
||||||
# Check for overridden instances
|
# Check for overridden instances
|
||||||
i_overridden, vevent = _find_overridden(i_overridden, vevents_overridden, recurrence_utc, dt_format)
|
i_overridden, vevent = _find_overridden(i_overridden, vevents_overridden, recurrence_utc, dt_format)
|
||||||
|
@ -443,10 +459,6 @@ def _expand(
|
||||||
if time_range_start is not None and time_range_end is not None:
|
if time_range_start is not None and time_range_end is not None:
|
||||||
for vevent in vevents_overridden:
|
for vevent in vevents_overridden:
|
||||||
dtstart = vevent.dtstart.value
|
dtstart = vevent.dtstart.value
|
||||||
dtend = vevent.dtend.value if hasattr(vevent, 'dtend') else dtstart
|
|
||||||
logger.debug(
|
|
||||||
"Filtering VEVENT with DTSTART: %s (type: %s), DTEND: %s (type: %s)",
|
|
||||||
dtstart, type(dtstart), dtend, type(dtend))
|
|
||||||
|
|
||||||
# Handle string values for DTSTART/DTEND
|
# Handle string values for DTSTART/DTEND
|
||||||
if isinstance(dtstart, str):
|
if isinstance(dtstart, str):
|
||||||
|
@ -457,14 +469,12 @@ def _expand(
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning("Invalid DTSTART format: %s, error: %s", dtstart, e)
|
logger.warning("Invalid DTSTART format: %s, error: %s", dtstart, e)
|
||||||
continue
|
continue
|
||||||
if isinstance(dtend, str):
|
|
||||||
try:
|
dtend = dtstart + duration if duration else dtstart
|
||||||
dtend = datetime.datetime.strptime(dtend, dt_format)
|
|
||||||
if all_day_event:
|
logger.debug(
|
||||||
dtend = dtend.date()
|
"Filtering VEVENT with DTSTART: %s (type: %s), DTEND: %s (type: %s)",
|
||||||
except ValueError as e:
|
dtstart, type(dtstart), dtend, type(dtend))
|
||||||
logger.warning("Invalid DTEND format: %s, error: %s", dtend, e)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Convert to datetime for comparison
|
# Convert to datetime for comparison
|
||||||
if all_day_event and isinstance(dtstart, datetime.date) and not isinstance(dtstart, datetime.datetime):
|
if all_day_event and isinstance(dtstart, datetime.date) and not isinstance(dtstart, datetime.datetime):
|
||||||
|
@ -487,10 +497,14 @@ def _expand(
|
||||||
|
|
||||||
# Rebuild component
|
# Rebuild component
|
||||||
|
|
||||||
# ToDo: Get rid of return vevent_recurrence if filtered_vevents is empty it's wrong behavior
|
if not filtered_vevents:
|
||||||
vevent_component.vevent_list = filtered_vevents if filtered_vevents else [vevent_recurrence]
|
element.text = ""
|
||||||
|
return element
|
||||||
|
else:
|
||||||
|
vevent_component.vevent_list = filtered_vevents
|
||||||
|
logger.debug("lbt: vevent_component %s", vevent_component)
|
||||||
|
|
||||||
element.text = vevent_component.serialize()
|
element.text = vevent_component.serialize()
|
||||||
logger.debug("Returning %d VEVENTs", len(vevent_component.vevent_list))
|
|
||||||
|
|
||||||
return element
|
return element
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue