(self, addRDate=False)
return rruleset
Get an rruleset created from self.

        If addRDate is True, add an RDATE for dtstart if it's not included in
        an RRULE or RDATE, and count is decremented if it exists.

        Note that for rules which don't match DTSTART, DTSTART may not appear
        in list(rruleset), although it should.  By default, an RDATE is not
        created in these cases, and count isn't updated, so dateutil may list
        a spurious occurrence.
Get an rruleset created from self.
Get an rruleset created from self .
def getrruleset(self, addRDate=False):
        """
        Get an rruleset created from self.

        If addRDate is True, add an RDATE for dtstart if it's not included in
        an RRULE or RDATE, and count is decremented if it exists.

        Note that for rules which don't match DTSTART, DTSTART may not appear
        in list(rruleset), although it should.  By default, an RDATE is not
        created in these cases, and count isn't updated, so dateutil may list
        a spurious occurrence.
        """
        rruleset = None
        for name in DATESANDRULES:
            addfunc = None
            for line in self.contents.get(name, ()):
                # don't bother creating a rruleset unless there's a rule
                if rruleset is None:
                    rruleset = rrule.rruleset()
                if addfunc is None:
                    addfunc = getattr(rruleset, name)

                try:
                    dtstart = self.dtstart.value
                except (AttributeError, KeyError):
                    # Special for VTODO - try DUE property instead
                    try:
                        if self.name == "VTODO":
                            dtstart = self.due.value
                        else:
                            # if there's no dtstart, just return None
                            logging.error('failed to get dtstart with VTODO')
                            return None
                    except (AttributeError, KeyError):
                        # if there's no due, just return None
                        logging.error('failed to find DUE at all.')
                        return None

                if name in DATENAMES:
                    if type(line.value[0]) == datetime.datetime:
                        list(map(addfunc, line.value))
                    elif type(line.value[0]) == datetime.date:
                        for dt in line.value:
                            addfunc(datetime.datetime(dt.year, dt.month, dt.day))
                    else:
                        # ignore RDATEs with PERIOD values for now
                        pass
                elif name in RULENAMES:
                    # a Ruby iCalendar library escapes semi-colons in rrules,
                    # so also remove any backslashes
                    value = line.value.replace('\\', '')
                    # If dtstart has no time zone, `until`
                    # shouldn't get one, either:
                    ignoretz = (not isinstance(dtstart, datetime.datetime) or
                                dtstart.tzinfo is None)
                    try:
                        until = rrule.rrulestr(value, ignoretz=ignoretz)._until
                    except ValueError:
                        # WORKAROUND: dateutil<=2.7.2 doesn't set the time zone
                        # of dtstart
                        if ignoretz:
                            raise
                        utc_now = datetime.datetime.now(datetime.timezone.utc)
                        until = rrule.rrulestr(value, dtstart=utc_now)._until

                    if until is not None and isinstance(dtstart,
                                                        datetime.datetime) and \
                            (until.tzinfo != dtstart.tzinfo):
                        # dateutil converts the UNTIL date to a datetime,
                        # check to see if the UNTIL parameter value was a date
                        vals = dict(pair.split('=') for pair in
                                    value.upper().split(';'))
                        if len(vals.get('UNTIL', '')) == 8:
                            until = datetime.datetime.combine(until.date(),
                                                              dtstart.time())
                        # While RFC2445 says UNTIL MUST be UTC, Chandler allows
                        # floating recurring events, and uses floating UNTIL
                        # values. Also, some odd floating UNTIL but timezoned
                        # DTSTART values have shown up in the wild, so put
                        # floating UNTIL values DTSTART's timezone
                        if until.tzinfo is None:
                            until = until.replace(tzinfo=dtstart.tzinfo)

                        if dtstart.tzinfo is not None:
                            until = until.astimezone(dtstart.tzinfo)

                        # RFC2445 actually states that UNTIL must be a UTC
                        # value. Whilst the changes above work OK, one problem
                        # case is if DTSTART is floating but UNTIL is properly
                        # specified as UTC (or with a TZID). In that case
                        # dateutil will fail datetime comparisons. There is no
                        # easy solution to this as there is no obvious timezone
                        # (at this point) to do proper floating time offset
                        # comparisons. The best we can do is treat the UNTIL
                        # value as floating. This could mean incorrect
                        # determination of the last instance. The better
                        # solution here is to encourage clients to use COUNT
                        # rather than UNTIL when DTSTART is floating.
                        if dtstart.tzinfo is None:
                            until = until.replace(tzinfo=None)

                    value_without_until = ';'.join(
                        pair for pair in value.split(';')
                        if pair.split('=')[0].upper() != 'UNTIL')
                    rule = rrule.rrulestr(value_without_until,
                                          dtstart=dtstart, ignoretz=ignoretz)
                    rule._until = until

                    # add the rrule or exrule to the rruleset
                    addfunc(rule)

                if (name == 'rrule' or name == 'rdate') and addRDate:
                    # rlist = rruleset._rrule if name == 'rrule' else rruleset._rdate
                    try:
                        # dateutils does not work with all-day
                        # (datetime.date) items so we need to convert to a
                        # datetime.datetime (which is what dateutils
                        # does internally)
                        if not isinstance(dtstart, datetime.datetime):
                            adddtstart = datetime.datetime.fromordinal(dtstart.toordinal())
                        else:
                            adddtstart = dtstart

                        if name == 'rrule':
                            if rruleset._rrule[-1][0] != adddtstart:
                                rruleset.rdate(adddtstart)
                                added = True
                                if rruleset._rrule[-1]._count is not None:
                                    rruleset._rrule[-1]._count -= 1
                            else:
                                added = False
                        elif name == 'rdate':
                            if rruleset._rdate[0] != adddtstart:
                                rruleset.rdate(adddtstart)
                                added = True
                            else:
                                added = False
                    except IndexError:
                        # it's conceivable that an rrule has 0 datetimes
                        added = False

        return rruleset
def getrruleset ( self , addRDate = False ) : rruleset = None for name in DATESANDRULES : addfunc = None for line in self . contents . get ( name , ( ) ) : # don't bother creating a rruleset unless there's a rule if rruleset is None : rruleset = rrule . rruleset ( ) if addfunc is None : addfunc = getattr ( rruleset , name ) try : dtstart = self . dtstart . value except ( AttributeError , KeyError ) : # Special for VTODO - try DUE property instead try : if self . name == "VTODO" : dtstart = self . due . value else : # if there's no dtstart, just return None logging . error ( 'failed to get dtstart with VTODO' ) return None except ( AttributeError , KeyError ) : # if there's no due, just return None logging . error ( 'failed to find DUE at all.' ) return None if name in DATENAMES : if type ( line . value [ 0 ] ) == datetime . datetime : list ( map ( addfunc , line . value ) ) elif type ( line . value [ 0 ] ) == datetime . date : for dt in line . value : addfunc ( datetime . datetime ( dt . year , dt . month , dt . day ) ) else : # ignore RDATEs with PERIOD values for now pass elif name in RULENAMES : # a Ruby iCalendar library escapes semi-colons in rrules, # so also remove any backslashes value = line . value . replace ( '\\' , '' ) # If dtstart has no time zone, `until` # shouldn't get one, either: ignoretz = ( not isinstance ( dtstart , datetime . datetime ) or dtstart . tzinfo is None ) try : until = rrule . rrulestr ( value , ignoretz = ignoretz ) . _until except ValueError : # WORKAROUND: dateutil<=2.7.2 doesn't set the time zone # of dtstart if ignoretz : raise utc_now = datetime . datetime . now ( datetime . timezone . utc ) until = rrule . rrulestr ( value , dtstart = utc_now ) . _until if until is not None and isinstance ( dtstart , datetime . datetime ) and ( until . tzinfo != dtstart . tzinfo ) : # dateutil converts the UNTIL date to a datetime, # check to see if the UNTIL parameter value was a date vals = dict ( pair . split ( '=' ) for pair in value . upper ( ) . split ( ';' ) ) if len ( vals . get ( 'UNTIL' , '' ) ) == 8 : until = datetime . datetime . combine ( until . date ( ) , dtstart . time ( ) ) # While RFC2445 says UNTIL MUST be UTC, Chandler allows # floating recurring events, and uses floating UNTIL # values. Also, some odd floating UNTIL but timezoned # DTSTART values have shown up in the wild, so put # floating UNTIL values DTSTART's timezone if until . tzinfo is None : until = until . replace ( tzinfo = dtstart . tzinfo ) if dtstart . tzinfo is not None : until = until . astimezone ( dtstart . tzinfo ) # RFC2445 actually states that UNTIL must be a UTC # value. Whilst the changes above work OK, one problem # case is if DTSTART is floating but UNTIL is properly # specified as UTC (or with a TZID). In that case # dateutil will fail datetime comparisons. There is no # easy solution to this as there is no obvious timezone # (at this point) to do proper floating time offset # comparisons. The best we can do is treat the UNTIL # value as floating. This could mean incorrect # determination of the last instance. The better # solution here is to encourage clients to use COUNT # rather than UNTIL when DTSTART is floating. if dtstart . tzinfo is None : until = until . replace ( tzinfo = None ) value_without_until = ';' . join ( pair for pair in value . split ( ';' ) if pair . split ( '=' ) [ 0 ] . upper ( ) != 'UNTIL' ) rule = rrule . rrulestr ( value_without_until , dtstart = dtstart , ignoretz = ignoretz ) rule . _until = until # add the rrule or exrule to the rruleset addfunc ( rule ) if ( name == 'rrule' or name == 'rdate' ) and addRDate : # rlist = rruleset._rrule if name == 'rrule' else rruleset._rdate try : # dateutils does not work with all-day # (datetime.date) items so we need to convert to a # datetime.datetime (which is what dateutils # does internally) if not isinstance ( dtstart , datetime . datetime ) : adddtstart = datetime . datetime . fromordinal ( dtstart . toordinal ( ) ) else : adddtstart = dtstart if name == 'rrule' : if rruleset . _rrule [ - 1 ] [ 0 ] != adddtstart : rruleset . rdate ( adddtstart ) added = True if rruleset . _rrule [ - 1 ] . _count is not None : rruleset . _rrule [ - 1 ] . _count -= 1 else : added = False elif name == 'rdate' : if rruleset . _rdate [ 0 ] != adddtstart : rruleset . rdate ( adddtstart ) added = True else : added = False except IndexError : # it's conceivable that an rrule has 0 datetimes added = False return rruleset