Skip to content

Commit

Permalink
Merge pull request #168 from niccokunzmann/timedelta
Browse files Browse the repository at this point in the history
Timedelta
  • Loading branch information
niccokunzmann authored Aug 23, 2024
2 parents fcab62a + f6a72c8 commit ae7d4df
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 7 deletions.
7 changes: 6 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ The resulting ``events`` are a list of `icalendar events <https://icalendar.read

``between(start, end)`` returns all events happening between a start and an end time. Both arguments can be `datetime.datetime`_, `datetime.date`_, tuples of numbers passed as arguments to `datetime.datetime`_ or strings in the form of
``%Y%m%d`` (``yyyymmdd``) and ``%Y%m%dT%H%M%SZ`` (``yyyymmddThhmmssZ``).
For examples, see ``at(a_date)`` above.
Additionally, the ``end`` argument can be a ``datetime.timedelta`` to express that the end is relative to the ``start``.
For examples of arguments, see ``at(a_date)`` above.

.. code:: Python
Expand Down Expand Up @@ -394,6 +395,10 @@ These **Occurrences** are used internally and convert to **Components** for furt
Changelog
---------

- v3.2.0

- Allow ``datetime.timedelta`` as second argument to ``between(absolute_time, datetime.timedelta())``

- v3.1.1

- Fix: Remove duplication of modification with same sequence number, see `Issue 164 <https://github.com/niccokunzmann/python-recurring-ical-events/issues/164>`_
Expand Down
15 changes: 12 additions & 3 deletions recurring_ical_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,9 @@ def __init__(self, components: Sequence[ComponentAdapter]):
)
else:
core = with_highest_sequence(core, component)
self.modifications: set[ComponentAdapter] = set(self.recurrence_id_to_modification.values())
self.modifications: set[ComponentAdapter] = set(
self.recurrence_id_to_modification.values()
)
del component
if core is None:
raise InvalidCalendar(
Expand Down Expand Up @@ -718,6 +720,7 @@ def is_in_span(self, span_start: Time, span_stop: Time) -> bool:
"""Return whether the component is in the span."""
return time_span_contains_event(span_start, span_stop, self.start, self.end)


class EventAdapter(ComponentAdapter):
"""An icalendar event adapter."""

Expand Down Expand Up @@ -1031,9 +1034,15 @@ def at(self, date: DateArgument):
dt = self.to_datetime(date)
return self._between(dt, dt + self._DELTAS[len(date) - 3])

def between(self, start: DateArgument, stop: DateArgument):
def between(self, start: DateArgument, stop: DateArgument | datetime.timedelta):
"""Return events at a time between start (inclusive) and end (inclusive)"""
return self._between(self.to_datetime(start), self.to_datetime(stop))
start = self.to_datetime(start)
stop = (
start + stop
if isinstance(stop, datetime.timedelta)
else self.to_datetime(stop)
)
return self._between(start, stop)

def _occurrences_to_components(
self, occurrences: list[Occurrence]
Expand Down
7 changes: 4 additions & 3 deletions test/test_issue_164_duplicated_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
See https://github.com/niccokunzmann/python-recurring-ical-events/issues/164
"""


def test_event_is_only_returned_once(calendars):
"""We should not see the same event twice!"""
events = calendars.issue_164_duplicated_event.at([2024,8])
events = calendars.issue_164_duplicated_event.at([2024, 8])
for event in events:
start = event["DTSTART"].dt
duration = event["DTEND"].dt - event["DTSTART"].dt
print("start {} duration {}".format(start, duration))
print(f"start {start} duration {duration}")
print(event.to_ical().decode())
assert len(events) == 2
assert len(events) == 2
27 changes: 27 additions & 0 deletions test/test_timedelta_for_between.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""This tests that a timedelta can be used as the second argument to between.
This is useful when you do not want to calculate this yourself.
"""

from datetime import timedelta

import pytest


@pytest.mark.parametrize(
("start", "delta", "count"),
[
("20190301", timedelta(days=3), 0),
("20190301", timedelta(days=5), 1),
("20190301", timedelta(days=3, hours=8), 0),
("20190301", timedelta(days=3, hours=9), 1),
("20190301", timedelta(days=3, hours=8, seconds=1), 1),
("20190304", timedelta(days=1), 1),
("20190304", timedelta(hours=8), 0),
("20190304", timedelta(hours=9), 1),
],
)
def test_event_with_between_and_timedelta(calendars, start, delta, count):
"""The event starts at 20190304T080000 and ends at 20190304T080000"""
events = calendars.one_event.between(start, delta)
assert len(events) == count

0 comments on commit ae7d4df

Please sign in to comment.