imip-agent

Change of imiptools/data.py

627:23f998c9dacd
imiptools/data.py
     1.1 --- a/imiptools/data.py	Sat Aug 01 01:25:21 2015 +0200
     1.2 +++ b/imiptools/data.py	Sat Aug 01 01:35:03 2015 +0200
     1.3 @@ -26,7 +26,8 @@
     1.4                              get_datetime_item as get_item_from_datetime, \
     1.5                              get_datetime_tzid, \
     1.6                              get_duration, get_period, \
     1.7 -                            get_tzid, to_timezone, to_utc_datetime
     1.8 +                            get_recurrence_start_point, \
     1.9 +                            get_tzid, to_datetime, to_timezone, to_utc_datetime
    1.10  from imiptools.period import Period, RecurringPeriod, period_overlaps
    1.11  from vCalendar import iterwrite, parse, ParseError, to_dict, to_node
    1.12  from vRecurrence import get_parameters, get_rule
    1.13 @@ -51,12 +52,44 @@
    1.14  
    1.15          """
    1.16          Return the recurrence identifier, normalised to a UTC datetime if
    1.17 -        specified as a datetime, converted to a date object otherwise. If no
    1.18 -        recurrence identifier is present, None is returned.
    1.19 +        specified as a datetime or date with accompanying time zone information,
    1.20 +        maintained as a date or floating datetime otherwise. If no recurrence
    1.21 +        identifier is present, None is returned.
    1.22 +
    1.23 +        Note that this normalised form of the identifier may well not be the
    1.24 +        same as the originally-specified identifier because that could have been
    1.25 +        specified using an accompanying TZID attribute, whereas the normalised
    1.26 +        form is effectively a converted datetime value.
    1.27          """
    1.28  
    1.29 -        recurrenceid = self.get_utc_datetime("RECURRENCE-ID")
    1.30 -        return recurrenceid and format_datetime(recurrenceid)
    1.31 +        if not self.has_key("RECURRENCE-ID"):
    1.32 +            return None
    1.33 +        dt, attr = self.get_datetime_item("RECURRENCE-ID")
    1.34 +        tzid = attr.get("TZID")
    1.35 +        if tzid:
    1.36 +            dt = to_timezone(to_datetime(dt, tzid), "UTC")
    1.37 +        return format_datetime(dt)
    1.38 +
    1.39 +    def get_recurrence_start_point(self, recurrenceid, tzid):
    1.40 +
    1.41 +        """
    1.42 +        Return the start point corresponding to the given 'recurrenceid', using
    1.43 +        the fallback 'tzid' to define the specific point in time referenced by
    1.44 +        the recurrence identifier if the identifier has a date representation.
    1.45 +
    1.46 +        If 'recurrenceid' is given as None, this object's recurrence identifier
    1.47 +        is used to obtain a start point, but if this object does not provide a
    1.48 +        recurrence, None is returned.
    1.49 +
    1.50 +        A start point is typically used to match free/busy periods which are
    1.51 +        themselves defined in terms of UTC datetimes.
    1.52 +        """
    1.53 +
    1.54 +        recurrenceid = recurrenceid or self.get_recurrenceid()
    1.55 +        if recurrenceid:
    1.56 +            return get_recurrence_start_point(recurrenceid, tzid)
    1.57 +        else:
    1.58 +            return None
    1.59  
    1.60      # Structure access.
    1.61  
    1.62 @@ -94,20 +127,6 @@
    1.63          dt, attr = t
    1.64          return dt
    1.65  
    1.66 -    def set_datetime(self, name, dt, tzid):
    1.67 -
    1.68 -        """
    1.69 -        Set a datetime for property 'name' using 'dt' and 'tzid', returning
    1.70 -        whether an update has occurred.
    1.71 -        """
    1.72 -
    1.73 -        if dt:
    1.74 -            old_value = self.get_value(name)
    1.75 -            self[name] = [get_item_from_datetime(dt, tzid)]
    1.76 -            return format_datetime(dt) != old_value
    1.77 -
    1.78 -        return False
    1.79 -
    1.80      def get_datetime_item(self, name):
    1.81          return get_datetime_item(self.details, name)
    1.82  
    1.83 @@ -159,14 +178,6 @@
    1.84  
    1.85          return get_periods(self, tzid, end)
    1.86  
    1.87 -    def set_period(self, period):
    1.88 -
    1.89 -        "Set the given 'period' as the main start and end."
    1.90 -
    1.91 -        result = self.set_datetime("DTSTART", period.get_start(), period.start_attr().get("TZID"))
    1.92 -        result = self.set_datetime("DTEND", period.get_end(), period.end_attr().get("TZID")) or result
    1.93 -        return result
    1.94 -
    1.95      def get_tzid(self):
    1.96  
    1.97          """
    1.98 @@ -189,6 +200,54 @@
    1.99  
   1.100          return self.get_value("SEQUENCE") is not None
   1.101  
   1.102 +    # Modification methods.
   1.103 +
   1.104 +    def set_datetime(self, name, dt, tzid=None):
   1.105 +
   1.106 +        """
   1.107 +        Set a datetime for property 'name' using 'dt' and the optional fallback
   1.108 +        'tzid', returning whether an update has occurred.
   1.109 +        """
   1.110 +
   1.111 +        if dt:
   1.112 +            old_value = self.get_value(name)
   1.113 +            self[name] = [get_item_from_datetime(dt, tzid)]
   1.114 +            return format_datetime(dt) != old_value
   1.115 +
   1.116 +        return False
   1.117 +
   1.118 +    def set_period(self, period):
   1.119 +
   1.120 +        "Set the given 'period' as the main start and end."
   1.121 +
   1.122 +        result = self.set_datetime("DTSTART", period.get_start())
   1.123 +        result = self.set_datetime("DTEND", period.get_end()) or result
   1.124 +        return result
   1.125 +
   1.126 +    def set_periods(self, periods):
   1.127 +
   1.128 +        """
   1.129 +        Set the given 'periods' as recurrence date properties, replacing the
   1.130 +        previous RDATE properties and ignoring any RRULE properties.
   1.131 +        """
   1.132 +
   1.133 +        update = False
   1.134 +
   1.135 +        old_values = self.get_values("RDATE")
   1.136 +        new_rdates = []
   1.137 +
   1.138 +        if self.has_key("RDATE"):
   1.139 +            del self["RDATE"]
   1.140 +
   1.141 +        for p in periods:
   1.142 +            if p.origin != "RRULE":
   1.143 +                new_rdates.append(get_period_item(p.get_start(), p.get_end()))
   1.144 +
   1.145 +        self["RDATE"] = new_rdates
   1.146 +
   1.147 +        # NOTE: To do: calculate the update status.
   1.148 +        return update
   1.149 +
   1.150  # Construction and serialisation.
   1.151  
   1.152  def make_calendar(nodes, method=None):