Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: crash when an event has mixed date and datetime #201

Open
1 of 3 tasks
fabien-michel opened this issue Nov 26, 2024 · 2 comments
Open
1 of 3 tasks

bug: crash when an event has mixed date and datetime #201

fabien-michel opened this issue Nov 26, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@fabien-michel
Copy link
Collaborator

fabien-michel commented Nov 26, 2024

Describe the bug

I've found the following event in the wild and it make the library crash on it becasue DTSTART is a date and DTEND is a datetime.
Possibly it is a invalid event, but it exists and the library is crashing even with skip_bad_series=True

ICS file

BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;VALUE=DATE:20230724
CREATED:20230606T153716Z
STATUS:CONFIRMED
SUMMARY:Congés
TRANSP:TRANSPARENT
DTSTAMP:20230704T085547Z
DTEND:20230817T000000Z
SEQUENCE:1
LAST-MODIFIED:20230731T161724Z
UID:19970901T130000Z[email protected]
END:VEVENT
END:VCALENDAR

Expected behavior

Event processed or event skipped (if skip_bad_series)
Tried to import the ics to Gnome Evolution and it take it without problem.

Console output

Traceback (most recent call last):
  File "xxx.py", line 49, in yyy
    ...
                     ^^^^^^^^^^^^^^^^^^^^^^^^
  File "xxx.py", line 104, in yyy
    zzz = recurring_ical_events.of(calendar, skip_bad_series=True).between(start_date, end_date)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 1446, in of
    return calendar_query(
           ^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 1290, in __init__
    component_adapter.collect_series_from(calendar, self._skip_errors)
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 1191, in collect_series_from
    result.append(self._series(components))
                  ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 610, in __init__
    self.compute_span_extension()
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 615, in compute_span_extension
    self.recurrence.extend_query_span_by
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 413, in extend_query_span_by
    return self.core.extend_query_span_by
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 259, in cached_property
    self.__dict__[name] = value = func(self)
                                  ^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 884, in extend_query_span_by
    subtract_from_start = self.duration
                          ^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 259, in cached_property
    self.__dict__[name] = value = func(self)
                                  ^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/recurring_ical_events.py", line 865, in duration
    return self.end - self.start
           ~~~~~~~~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'datetime.date'

Version:

pip list

Additional context

Suggested implementation

    @cached_property
    def duration(self) -> datetime.timedelta:
        """The duration of the component."""
        start, end = make_comparable((self.start, self.end))
        return end - start

We're using Polar.sh so you can upvote and help fund this issue. We receive the funding once the issue is completed & confirmed by you. Thank you in advance for helping prioritize & fund our work. Fund with Polar
@fabien-michel fabien-michel added the bug Something isn't working label Nov 26, 2024
@fabien-michel
Copy link
Collaborator Author

.duration is called without making use of make_comparable in extend_query_span_by and in between. It fail at both locations.
The change propose to call make_comparable inside .duration but I'm not sure it is a nice fix.

@niccokunzmann
Copy link
Owner

Thanks for reporting!

I think, that might be a good place to fix it... I also think, the event is not standard compatible, so thanks for catching this!

We have to consider two cases here:

  1. start is date, end is datetime -> make start a datetime
  2. end is date, start is datetime -> make end a datetime

There is another edge case like this which will not error:

DTSTART is date, duration is timedelta with seconds

>>> datetime.date(2024, 10, 10) + datetime.timedelta(hours=26)
datetime.date(2024, 10, 11)

Tests for this issue:

  • DTSTART is date, DTEND is datetime
    • Event
    • Todo
  • DTSTART is datetime, DTEND is date
    • Event
    • Todo
  • DTSTART is date, DURATION is timedelta with hours
    • Event
    • Todo

With these tests, the issue is solved for other cases like this in the wild. My guess is that the .end property should be adapted, not .duration.

I am looking at it from a place of perfection, I guess...

What are your thoughts on this? Would you like to work on it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants