diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py --- a/pykolab/xml/event.py +++ b/pykolab/xml/event.py @@ -152,6 +152,23 @@ self._categories.append(ustr(category)) self.event.setCategories(self._categories) + def add_recurrence_date(self, _datetime): + valid_datetime = False + if isinstance(_datetime, datetime.date): + valid_datetime = True + + if isinstance(_datetime, datetime.datetime): + # If no timezone information is passed on, make it UTC + if _datetime.tzinfo is None: + _datetime = _datetime.replace(tzinfo=pytz.utc) + + valid_datetime = True + + if not valid_datetime: + raise InvalidEventDateError, _("Rdate needs datetime.date or datetime.datetime instance, got %r") % (type(_datetime)) + + self.event.addRecurrenceDate(xmlutils.to_cdatetime(_datetime, True)) + def add_exception_date(self, _datetime): valid_datetime = False if isinstance(_datetime, datetime.date): @@ -481,6 +498,9 @@ return "%s - %s" % (start.strftime(date_format + " " + time_format), end.strftime(end_format)) + def get_recurrence_dates(self): + return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.recurrenceDates()) + def get_exception_dates(self): return map(lambda _: xmlutils.from_cdatetime(_, True), self.event.exceptionDates()) @@ -665,6 +685,13 @@ result.append(rrule.to_ical()) return result + def get_ical_rdate(self): + rdates = self.get_recurrence_dates() + for i in range(len(rdates)): + rdates[i] = icalendar.prop.vDDDLists(rdates[i]) + + return rdates + def get_location(self): return self.event.location() @@ -829,6 +856,10 @@ for _datetime in _datetimes: self.add_exception_date(_datetime) + def set_recurrence_dates(self, _datetimes): + for _datetime in _datetimes: + self.add_recurrence_date(_datetime) + def add_custom_property(self, name, value): if not name.upper().startswith('X-'): raise ValueError, _("Invalid custom property name %r") % (name) @@ -946,6 +977,23 @@ def set_ical_uid(self, uid): self.set_uid(str(uid)) + def set_ical_rdate(self, rdate): + rdates = [] + # rdate here can be vDDDLists or a list of vDDDLists, why?! + if isinstance(rdate, icalendar.prop.vDDDLists): + rdate = [rdate] + + for _rdate in rdate: + if isinstance(_rdate, icalendar.prop.vDDDLists): + tzid = None + if hasattr(_rdate, 'params') and 'TZID' in _rdate.params: + tzid = _rdate.params['TZID'] + dts = icalendar.prop.vDDDLists.from_ical(_rdate.to_ical(), tzid) + for datetime in dts: + rdates.append(datetime) + + self.set_recurrence_dates(rdates) + def set_ical_recurrenceid(self, value, params): try: self.thisandfuture = params.get('RANGE', '') == 'THISANDFUTURE' @@ -1316,7 +1364,7 @@ return msg def is_recurring(self): - return self.event.recurrenceRule().isValid() + return self.event.recurrenceRule().isValid() or len(self.get_recurrence_dates()) > 0 def to_event_cal(self): from kolab.calendaring import EventCal diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py --- a/tests/unit/test-003-event.py +++ b/tests/unit/test-003-event.py @@ -89,6 +89,25 @@ END:VEVENT """ +ical_event_rdate = """ +BEGIN:VEVENT +UID:7a35527d-f783-4b58-b404-b1389bd2fc57 +DTSTAMP;VALUE=DATE-TIME:20140407T122311Z +CREATED;VALUE=DATE-TIME:20140407T122245Z +LAST-MODIFIED;VALUE=DATE-TIME:20140407T122311Z +DTSTART;TZID=Europe/Zurich;VALUE=DATE-TIME:20140523T110000 +DURATION:PT1H30M0S +RDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140530T110000 +RDATE;TZID=Europe/Zurich;VALUE=DATE-TIME:20140620T110000 +SUMMARY:Summary +LOCATION:Location +DESCRIPTION:Description +SEQUENCE:2 +CLASS:PUBLIC +ORGANIZER;CN=Doe\, John:mailto:john.doe@example.org +END:VEVENT +""" + xml_event = """ @@ -961,6 +980,31 @@ self.assertEqual(event.get_attendee("jack@example.org").get_name(), "Jack") self.assertRaises(ValueError, exception.get_attendee, "somebody@else.com") # not addded to exception + def test_028_rdate(self): + event = event_from_ical(ical_event_rdate) + + self.assertTrue(event.is_recurring()) + self.assertEqual(len(event.get_recurrence_dates()), 2) + self.assertIsInstance(event.get_recurrence_dates()[0], datetime.datetime) + + rdates = event.get_recurrence_dates() + self.assertEqual(str(rdates[0]), "2014-05-30 11:00:00+02:00") + self.assertEqual(str(rdates[1]), "2014-06-20 11:00:00+02:00") + + dt = datetime.datetime(2014, 8, 15, 10, 0, 0, tzinfo=pytz.timezone("Europe/Zurich")) + event.add_recurrence_date(dt) + rdates = event.get_recurrence_dates() + self.assertEqual(str(rdates[2]), "2014-08-15 10:00:00+02:00") + + itip = event.as_string_itip() + rdates = [] + for line in itip.split("\n"): + if re.match('^RDATE', line): + rdates.append(line.strip().split(':')[1]) + self.assertEqual("TZID=Europe/Zurich", line.split(':')[0].split(';')[1]) + + self.assertEqual(rdates, ["20140530T110000", "20140620T110000", "20140815T100000"]) + def _find_prop_in_list(self, diff, name): for prop in diff: if prop['property'] == name: