Skip to content

Commit

Permalink
Merge pull request #30 from dlichtistw/dateutil
Browse files Browse the repository at this point in the history
Tests and endless events
  • Loading branch information
Thomas Irgang authored Oct 8, 2018
2 parents a61d2a7 + dff4e35 commit 3554c68
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 11 deletions.
14 changes: 8 additions & 6 deletions icalevents/icalparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ def copy_to(self, new_start=None, uid=None):
:param uid: UID of new event
:return: new event
"""
duration = self.end - self.start

if not new_start:
new_start = self.start

Expand All @@ -109,7 +107,11 @@ def copy_to(self, new_start=None, uid=None):
ne.summary = self.summary
ne.description = self.description
ne.start = new_start
ne.end = (new_start + duration)

if self.end:
duration = self.end - self.start
ne.end = (new_start + duration)

ne.all_day = (self.all_day and (new_start - self.start).seconds == 0)
ne.uid = uid

Expand All @@ -131,10 +133,10 @@ def create_event(component, tz=UTC):

if component.get('dtend'):
event.end = normalize(component.get('dtend').dt, tz=tz)
elif component.get('duration'):
elif component.get('duration'): # compute implicit end as start + duration
event.end = event.start + component.get('duration').dt
else:
raise ValueError("Event has neither end, nor duration property.")
else: # compute implicit end as start + 0
event.end = event.start

event.summary = str(component.get('summary'))
event.description = str(component.get('description'))
Expand Down
19 changes: 19 additions & 0 deletions test/test_data/duration.ics
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART:20180110
DURATION:P3D
DESCRIPTION:Event with duration (3 days), instead of explicit end.
SUMMARY:Duration Event
END:VEVENT
BEGIN:VEVENT
DTSTART:20180115T100000
DURATION:PT3H
DESCRIPTION:Event with duration (3 hours), instead of explicit end.
SUMMARY:Duration Event
END:VEVENT
BEGIN:VEVENT
DTSTART:20180120T120000
DESCRIPTION:Event without explicit dtend, nor duration property.
SUMMARY:Short event
END:VEVENT
END:VCALENDAR
13 changes: 11 additions & 2 deletions test/test_data/recurring.ics
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@ END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20181003T100000
DTEND;TZID=Europe/Berlin:20181003T120000
DESCRIPTION:Event recurring on wednesday each week
SUMARRY:Recurring event
DESCRIPTION:Event recurring on wednesday each week, except on 2018-10-29
SUMARRY:Recurring Event
RRULE:FREQ=WEEKLY;BYDAY=MO
EXDATE;TZID=Europe/Berlin:20181029T100000
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20180601T100000
DTEND;TZID=Europe/Berlin:20180601T120000
DESCRIPTION:Event recurring on friday each week, except on 2018-06-08/22
SUMARRY:Recurring Event
RRULE:FREQ=WEEKLY;BYDAY=FR
EXDATE;TZID=Europe/Berlin:20180608T100000
EXDATE;TZID=Europe/Berlin:20180622T100000
END:VEVENT
END:VCALENDAR
55 changes: 54 additions & 1 deletion test/test_icalevents.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import unittest
from icalevents import icalevents
from datetime import date, timedelta
from datetime import date, timedelta, datetime
from time import sleep
from dateutil.relativedelta import relativedelta
from dateutil.tz import UTC
from re import search


class ICalEventsTests(unittest.TestCase):
Expand Down Expand Up @@ -31,6 +34,25 @@ def test_events(self):

self.assertEqual(len(evs), 2, "two events are found")

def test_events_duration(self):
ical = "test/test_data/duration.ics"
start = date(2018, 1, 1)
end = date(2018, 2, 1)

evs = icalevents.events(file=ical, start=start, end=end)

e1 = evs[0]
self.assertEqual(e1.start.day, 10, "explicit event start")
self.assertEqual(e1.end.day, 13, "implicit event end")

e2 = evs[1]
self.assertEqual(e2.start.hour, 10, "explicit event start")
self.assertEqual(e2.end.hour, 13, "implicit event end")

e3 = evs[2]
self.assertEqual(e3.start.hour, 12, "explicit event start")
self.assertEqual(e3.end.hour, 12, "implicit event end")

def test_events_recurring(self):
ical = "test/test_data/recurring.ics"
start = date(2018, 10, 15)
Expand All @@ -47,6 +69,17 @@ def test_events_recurring(self):
self.assertEqual(e2.start.tzinfo.utcoffset(e2.start), timedelta(seconds=3600), "check UTC offset without DST")

self.assertEqual(e2.start.day, 5, "Check observance of exdate.")

def test_events_exdates(self):
ical = "test/test_data/recurring.ics"
start = date(2018, 6, 1)
end = date(2018, 6, 30)

evs = icalevents.events(file=ical, start=start, end=end)

self.assertEqual(evs[0].start.day, 1, "check first recurrence.")
self.assertEqual(evs[1].start.day, 15, "check first exdate.")
self.assertEqual(evs[2].start.day, 29, "check second exdate.")

def test_event_attributes(self):
ical = "test/test_data/basic.ics"
Expand Down Expand Up @@ -111,3 +144,23 @@ def test_string_data(self):

self.assertTrue(icalevents.all_done(key), "request is finished")
self.assertEqual(len(icalevents.latest_events(key)), 2, "two events are found")

def test_event_str(self):
ical = "test/test_data/duration.ics"
start = date(2018, 1, 1)
end = date(2018, 2, 1)
n = datetime.now(UTC)
m = relativedelta(hour=0, minute=0, second=0, microsecond=0)

evs = icalevents.events(file=ical, start=start, end=end)

e1 = evs[0]
self.assertIsNotNone(search(r"ended", str(e1.copy_to(n - relativedelta(days=5) + m))), "stringify past event")
self.assertIsNotNone(search(r"today", str(e1.copy_to(n - relativedelta(days=1) + m))), "stringify ongoing event")
self.assertIsNotNone(search(r"days left", str(e1.copy_to(n + relativedelta(days=3) + m))), "stringify future event")

e2 = evs[1]
self.assertIsNotNone(search(r"ended", str(e2.copy_to(n - relativedelta(hours=5)))), "stringify past event")
self.assertIsNotNone(search(r"now", str(e2.copy_to(n - relativedelta(hours=1)))), "stringify ongoing event")
self.assertIsNotNone(search(r"hours left", str(e2.copy_to(n + relativedelta(hours=3)))), "stringify future event")
self.assertIsNotNone(search(r"days left", str(e2.copy_to(n + relativedelta(days=3)))), "stringify future event")
8 changes: 6 additions & 2 deletions test/test_icalparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_time_left(self):
def test_event_copy_to(self):
new_start = datetime(year=2017, month=2, day=5, hour=12, minute=5, tzinfo=UTC)
eventC = self.eventA.copy_to(new_start)
new_uid = 1234567890

self.assertNotEqual(eventC.uid, self.eventA.uid, "new event has new UID")
self.assertEqual(eventC.start, new_start, "new event has new start")
Expand All @@ -47,8 +48,8 @@ def test_event_copy_to(self):
self.assertEqual(eventC.summary, self.eventA.summary, "copy to: summary")
self.assertEqual(eventC.description, self.eventA.description, "copy to: description")

eventD = eventC.copy_to()
self.assertNotEqual(eventD.uid, eventC.uid, "new event has new UID")
eventD = eventC.copy_to(uid=new_uid)
self.assertEqual(eventD.uid, new_uid, "new event has specified UID")
self.assertEqual(eventD.start, eventC.start, "new event has same start")
self.assertEqual(eventD.end, eventC.end, "new event has same end")
self.assertEqual(eventD.all_day, eventC.all_day, "new event is no all day event")
Expand Down Expand Up @@ -84,3 +85,6 @@ def test_normalize(self):
self.assertEqual(3, norm.second, "second")
self.assertEqual(0, norm.microsecond, "microsecond")
self.assertEqual(UTC, norm.tzinfo, "timezone")

with self.assertRaises(ValueError, msg="type check effective"):
icalevents.icalparser.normalize(None)

0 comments on commit 3554c68

Please sign in to comment.