Beispiel #1
0
 def coerceIfDatetime(value):
     if isinstance(value, datetime):
         if convertFloating and tzinfo == view.tzinfo.floating:
             value = coerceTimeZone(view, value, tzinfo).replace(tzinfo=None)
         else:
             value = coerceTimeZone(view, value, tzinfo)
     return value
 def coerceIfDatetime(value):
     if isinstance(value, datetime):
         if convertFloating and tzinfo == view.tzinfo.floating:
             value = coerceTimeZone(view, value,
                                    tzinfo).replace(tzinfo=None)
         else:
             value = coerceTimeZone(view, value, tzinfo)
     return value
    def createDateUtilFromRule(self,
                               dtstart,
                               ignoreIsCount=True,
                               convertFloating=False,
                               ignoreShortFrequency=True):
        """Return an appropriate dateutil.rrule.rruleset.

        @param dtstart: The start time for the recurrence rule
        @type  dtstart: C{datetime}

        @param ignoreIsCount: Whether the isCount flag should be used to convert
                              until endtimes to a count. Converting to count
                              takes extra cycles and is only necessary when
                              the rule is going to be serialized
        @type  ignoreIsCount: C{bool}

        @param convertFloating: Whether or not to allow view.tzinfo.floating
                                in datetimes of the rruleset. If C{True},
                                naive datetimes are used instead. This is
                                needed for exporting floating events to
                                icalendar format.
        @type  convertFloating: C{bool}

        @param ignoreShortFrequency: If ignoreShortFrequency is True, replace
                                     hourly or more frequent rules with a single
                                     RDATE matching dtstart, so as to avoid 
                                     wasting millions of cycles on nonsensical
                                     recurrence rules.
        @type  ignoreShortFrequency: C{bool}

        @rtype: C{dateutil.rrule.rruleset}

        """
        view = self.itsView
        args = (ignoreIsCount, convertFloating)
        ruleset = rruleset()
        for rtype in 'rrule', 'exrule':
            for rule in getattr(self, rtype + 's', []):
                if ignoreShortFrequency and rule.freq in SHORT_FREQUENCIES:
                    # too-frequent rule, as Admiral Ackbar said, "IT'S A TRAP!"
                    ruleset.rdate(dtstart)
                    return ruleset
                rule_adder = getattr(ruleset, rtype)
                rule_adder(rule.createDateUtilFromRule(dtstart, *args))

        for datetype in 'rdate', 'exdate':
            for date in getattr(self, datetype + 's', []):
                if convertFloating and date.tzinfo == view.tzinfo.floating:
                    date = date.replace(tzinfo=None)
                else:
                    date = coerceTimeZone(view, date, dtstart.tzinfo)
                getattr(ruleset, datetype)(date)

        if (ignoreIsCount and not getattr(self, 'rrules', [])
                and getattr(self, 'rdates', [])):
            # no rrule, but there are RDATEs, create an RDATE for dtstart, or it
            # won't appear to be part of the rule
            ruleset.rdate(dtstart)

        return ruleset
Beispiel #4
0
    def createDateUtilFromRule(self, dtstart,
                               ignoreIsCount=True,
                               convertFloating=False,
                               ignoreShortFrequency=True):
        """Return an appropriate dateutil.rrule.rruleset.

        @param dtstart: The start time for the recurrence rule
        @type  dtstart: C{datetime}

        @param ignoreIsCount: Whether the isCount flag should be used to convert
                              until endtimes to a count. Converting to count
                              takes extra cycles and is only necessary when
                              the rule is going to be serialized
        @type  ignoreIsCount: C{bool}

        @param convertFloating: Whether or not to allow view.tzinfo.floating
                                in datetimes of the rruleset. If C{True},
                                naive datetimes are used instead. This is
                                needed for exporting floating events to
                                icalendar format.
        @type  convertFloating: C{bool}

        @param ignoreShortFrequency: If ignoreShortFrequency is True, replace
                                     hourly or more frequent rules with a single
                                     RDATE matching dtstart, so as to avoid 
                                     wasting millions of cycles on nonsensical
                                     recurrence rules.
        @type  ignoreShortFrequency: C{bool}

        @rtype: C{dateutil.rrule.rruleset}

        """
        view = self.itsView
        args = (ignoreIsCount, convertFloating)
        ruleset = rruleset()
        for rtype in 'rrule', 'exrule':
            for rule in getattr(self, rtype + 's', []):
                if ignoreShortFrequency and rule.freq in SHORT_FREQUENCIES:
                    # too-frequent rule, as Admiral Ackbar said, "IT'S A TRAP!"
                    ruleset.rdate(dtstart)
                    return ruleset
                rule_adder = getattr(ruleset, rtype)
                rule_adder(rule.createDateUtilFromRule(dtstart, *args))
        
        for datetype in 'rdate', 'exdate':
            for date in getattr(self, datetype + 's', []):
                if convertFloating and date.tzinfo == view.tzinfo.floating:
                    date = date.replace(tzinfo=None)
                else:
                    date = coerceTimeZone(view, date, dtstart.tzinfo)
                getattr(ruleset, datetype)(date)
        
        if (ignoreIsCount and 
            not getattr(self, 'rrules', []) and 
            getattr(self, 'rdates', [])):
            # no rrule, but there are RDATEs, create an RDATE for dtstart, or it
            # won't appear to be part of the rule
            ruleset.rdate(dtstart)
        
        return ruleset
    def setRuleFromDateUtil(self, rrule):
        """Extract attributes from rrule, set them in self.

        @param rrule: The rule to marshall into Chandler
        @type  rrule: C{dateutil.rrule.rrule}

        """
        view = self.itsView
        self.untilIsDate = False
        until = None  # assume no limit
        if rrule._count is not None:
            self.isCount = True
            until = rrule[-1]
        self.wkst = fromDateUtilWeekday(rrule._wkst)
        self.freq = fromDateUtilFrequency(rrule._freq)

        # ignore byweekday if freq is WEEKLY and day correlates with dtstart
        # because it was automatically set by dateutil
        if rrule._freq != dateutil.rrule.WEEKLY or \
           len(rrule._byweekday or ()) != 1 or \
           rrule._dtstart.weekday() != rrule._byweekday[0]:
            listOfDayTuples = []
            if rrule._byweekday:
                # Day tuples are (dayOrdinal, n-th week of the month),
                # 0 means all weeks
                listOfDayTuples = [(day, 0) for day in rrule._byweekday]
            if rrule._bynweekday is not None:
                listOfDayTuples.extend(rrule._bynweekday)
            if len(listOfDayTuples) > 0:
                self.byweekday = []
                for day, n in listOfDayTuples:
                    day = fromDateUtilWeekday(day)
                    self.byweekday.append(WeekdayAndPositionStruct(day, n))
        if rrule._until is not None:
            until = rrule._until
        if rrule._interval != 1:
            self.interval = rrule._interval
        if until is None:
            if self.hasLocalAttributeValue('until'):
                del self.until
        else:
            if until.tzinfo is None:
                self.until = until.replace(tzinfo=view.tzinfo.floating)
            else:
                self.until = coerceTimeZone(view, until, view.tzinfo.default)

        for key in self.listNames:
            # TODO: cache getattr(rrule, '_' + key)
            value = getattr(rrule, '_' + key)
            if key == 'bymonthday':
                if value is not None:
                    value += (rrule._bynmonthday or ())
            if value is not None and \
               (key not in self.interpretedNames or \
               len(value) > 1):
                # cast tuples to list
                setattr(self, key, list(value))
        # bymonthday and bymonth may be set automatically by dateutil, if so,
        # unset them
        if rrule._freq in (dateutil.rrule.MONTHLY, dateutil.rrule.YEARLY):
            if len(rrule._bymonthday) == 1 and len(rrule._bynmonthday) == 0:
                if rrule._bymonthday[0] == rrule._dtstart.day:
                    del self.bymonthday
        if rrule._freq == dateutil.rrule.YEARLY:
            if len(rrule._bymonth or ()) == 1 and \
                   rrule._byweekday is None and \
                   len(rrule._bynweekday or ()) == 0:
                if rrule._bymonth[0] == rrule._dtstart.month:
                    del self.bymonth
Beispiel #6
0
    def setRuleFromDateUtil(self, rrule):
        """Extract attributes from rrule, set them in self.

        @param rrule: The rule to marshall into Chandler
        @type  rrule: C{dateutil.rrule.rrule}

        """
        view = self.itsView
        self.untilIsDate = False
        until = None # assume no limit
        if rrule._count is not None:
            self.isCount = True
            until = rrule[-1]
        self.wkst = fromDateUtilWeekday(rrule._wkst)
        self.freq = fromDateUtilFrequency(rrule._freq)

        # ignore byweekday if freq is WEEKLY and day correlates with dtstart
        # because it was automatically set by dateutil
        if rrule._freq != dateutil.rrule.WEEKLY or \
           len(rrule._byweekday or ()) != 1 or \
           rrule._dtstart.weekday() != rrule._byweekday[0]:
            listOfDayTuples = []
            if rrule._byweekday:
                # Day tuples are (dayOrdinal, n-th week of the month),
                # 0 means all weeks
                listOfDayTuples=[(day, 0) for day in rrule._byweekday]
            if rrule._bynweekday is not None:
                listOfDayTuples.extend(rrule._bynweekday)
            if len(listOfDayTuples) > 0:
                self.byweekday = []
                for day, n in listOfDayTuples:
                    day = fromDateUtilWeekday(day)
                    self.byweekday.append(WeekdayAndPositionStruct(day, n))
        if rrule._until is not None:
            until = rrule._until
        if rrule._interval != 1:
            self.interval = rrule._interval
        if until is None:
            if self.hasLocalAttributeValue('until'):
                del self.until
        else:
            if until.tzinfo is None:
                self.until = until.replace(tzinfo=view.tzinfo.floating)
            else:
                self.until = coerceTimeZone(view, until, view.tzinfo.default)

        for key in self.listNames:
            # TODO: cache getattr(rrule, '_' + key)
            value = getattr(rrule, '_' + key)
            if key == 'bymonthday':
                if value is not None:
                    value += (rrule._bynmonthday or ())
            if value is not None and \
               (key not in self.interpretedNames or \
               len(value) > 1):
                # cast tuples to list
                setattr(self, key, list(value))
        # bymonthday and bymonth may be set automatically by dateutil, if so,
        # unset them
        if rrule._freq in (dateutil.rrule.MONTHLY, dateutil.rrule.YEARLY):
            if len(rrule._bymonthday) == 1 and len(rrule._bynmonthday) == 0:
                if rrule._bymonthday[0] == rrule._dtstart.day:
                    del self.bymonthday
        if rrule._freq == dateutil.rrule.YEARLY:
            if len(rrule._bymonth or ()) == 1 and \
                   rrule._byweekday is None and \
                   len(rrule._bynweekday or ()) == 0:
                if rrule._bymonth[0] == rrule._dtstart.month:
                    del self.bymonth