summaryrefslogtreecommitdiffstats
path: root/pykolab
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-03-04 15:50:51 -0500
committerThomas Bruederli <bruederli@kolabsys.com>2014-03-04 15:50:51 -0500
commitf4b9812231a169f48fd0a45fa788d4aa09026387 (patch)
tree23c6d5a30e0a61b36749572d6abfb6932d483a54 /pykolab
parent74c17bde3f0eb6d83730d3711c8b9d8f68c6c2dc (diff)
downloadpykolab-f4b9812231a169f48fd0a45fa788d4aa09026387.tar.gz
Basic support for recurring resource invitations
Diffstat (limited to 'pykolab')
-rw-r--r--pykolab/xml/event.py38
-rw-r--r--pykolab/xml/utils.py7
2 files changed, 39 insertions, 6 deletions
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index 181c270..a165bcf 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -624,6 +624,10 @@ class Event(object):
def set_recurrence(self, recurrence):
self.event.setRecurrenceRule(recurrence)
+ # reset eventcal instance
+ if hasattr(self, 'eventcal'):
+ del self.eventcal
+
def set_start(self, _datetime):
valid_datetime = False
if isinstance(_datetime, datetime.date):
@@ -808,7 +812,13 @@ class Event(object):
self.eventcal = self.to_event_cal()
next_cdatetime = self.eventcal.getNextOccurence(xmlutils.to_cdatetime(datetime, True))
- return xmlutils.from_cdatetime(next_cdatetime, True) if next_cdatetime is not None else None
+ next_datetime = xmlutils.from_cdatetime(next_cdatetime, True) if next_cdatetime is not None else None
+
+ # cut infinite recurrence at a reasonable point
+ if next_datetime and not self.get_last_occurrence() and next_datetime > self._recurrence_end():
+ next_datetime = None
+
+ return next_datetime
def get_occurence_end_date(self, datetime):
if not datetime:
@@ -820,12 +830,18 @@ class Event(object):
end_cdatetime = self.eventcal.getOccurenceEndDate(xmlutils.to_cdatetime(datetime, True))
return xmlutils.from_cdatetime(end_cdatetime, True) if end_cdatetime is not None else None
- def get_last_occurrence(self):
+ def get_last_occurrence(self, force=False):
if not hasattr(self, 'eventcal'):
self.eventcal = self.to_event_cal()
last = self.eventcal.getLastOccurrence()
- return xmlutils.from_cdatetime(last, True) if last is not None else None
+ last_datetime = xmlutils.from_cdatetime(last, True) if last is not None else None
+
+ # we're forced to return some date
+ if last_datetime is None and force:
+ last_datetime = self._recurrence_end()
+
+ return last_datetime
def get_next_instance(self, datetime):
next_start = self.get_next_occurence(datetime)
@@ -842,6 +858,22 @@ class Event(object):
return None
+ def _recurrence_end(self):
+ """
+ Determine a reasonable end date for infinitely recurring events
+ """
+ rrule = self.event.recurrenceRule()
+ if rrule.isValid() and rrule.count() < 0 and not rrule.end().isValid():
+ now = datetime.datetime.now()
+ switch = {
+ kolabformat.RecurrenceRule.Yearly: 100,
+ kolabformat.RecurrenceRule.Monthly: 20
+ }
+ intvl = switch[rrule.frequency()] if rrule.frequency() in switch else 10
+ return self.get_start().replace(year=now.year + intvl)
+
+ return xmlutils.from_cdatetime(rrule.end(), True)
+
class EventIntegrityError(Exception):
def __init__(self, message):
diff --git a/pykolab/xml/utils.py b/pykolab/xml/utils.py
index 780932d..2fddb24 100644
--- a/pykolab/xml/utils.py
+++ b/pykolab/xml/utils.py
@@ -1,16 +1,17 @@
import datetime
import pytz
import kolabformat
+from dateutil.tz import tzlocal
def to_dt(dt):
"""
Convert a naive date or datetime to a tz-aware datetime.
"""
- if isinstance(dt, datetime.date) and not isinstance(dt, datetime.datetime) or not hasattr(dt, 'hour'):
- dt = datetime.datetime(dt.year, dt.month, dt.day, 0, 0, 0, 0)
+ if isinstance(dt, datetime.date) and not isinstance(dt, datetime.datetime) or dt is not None and not hasattr(dt, 'hour'):
+ dt = datetime.datetime(dt.year, dt.month, dt.day, 0, 0, 0, 0, tzinfo=tzlocal())
- else:
+ elif isinstance(dt, datetime.datetime):
if dt.tzinfo == None:
return dt.replace(tzinfo=pytz.utc)