Beispiel #1
0
 def _gen_dtend_rrule(dtstarts, vevent):
     """Generate an rdate or rrule from a list of dates and add it to the vevent"""
     interval = Remind._interval(dtstarts)
     if interval > 0 and interval % 7 == 0:
         rset = rrule.rruleset()
         rset.rrule(rrule.rrule(freq=rrule.WEEKLY, interval=interval//7, count=len(dtstarts)))
         vevent.rruleset = rset
     elif interval > 1:
         rset = rrule.rruleset()
         rset.rrule(rrule.rrule(freq=rrule.DAILY, interval=interval, count=len(dtstarts)))
         vevent.rruleset = rset
     elif interval > 0:
         if isinstance(dtstarts[0], datetime):
             rset = rrule.rruleset()
             rset.rrule(rrule.rrule(freq=rrule.DAILY, count=len(dtstarts)))
             vevent.rruleset = rset
         else:
             vevent.add('dtend').value = dtstarts[-1] + timedelta(days=1)
     else:
         rset = rrule.rruleset()
         if isinstance(dtstarts[0], datetime):
             for dat in dtstarts:
                 rset.rdate(dat)
         else:
             for dat in dtstarts:
                 rset.rdate(datetime(dat.year, dat.month, dat.day))
         # temporary set dtstart to a different date, so it's not
         # removed from rset by python-vobject works around bug in
         # Android:
         # https://github.com/rfc2822/davdroid/issues/340
         vevent.dtstart.value = dtstarts[0] - timedelta(days=1)
         vevent.rruleset = rset
         vevent.dtstart.value = dtstarts[0]
         if not isinstance(dtstarts[0], datetime):
             vevent.add('dtend').value = dtstarts[0] + timedelta(days=1)
    def get_upcoming_event_list(self, timedelta_in_days):
        now = datetime.now(timezone.utc)
        end_date = now + timedelta(days=timedelta_in_days)

        events = []
        for component in self.calendar.walk():
            if component.name == "VEVENT":
                summary = component.get('summary')
                description = component.get('description')
                dtstart = component.get('dtstart').dt
                if dtstart > now and dtstart < end_date:
                    events.append(UpcomingEvent(summary, description, dtstart))
                elif component.get('RRULE'):
                    rruleset = rrule.rruleset()
                    rruleset.rrule(
                        rrule.rrulestr(
                            component.get('RRULE').to_ical().decode('utf-8'),
                            dtstart=dtstart))
                    recurring_dates = rruleset.between(now, end_date)
                    if len(recurring_dates) > 0:
                        events.append(
                            UpcomingEvent(summary, description,
                                          recurring_dates[0]))

        return sorted(events, key=lambda event: event.dtstart)
Beispiel #3
0
    def _calculate_recurring(self, element, recurring_month):
        rules = rruleset()
        dtstart = element.get('dtstart').dt
        if isinstance(dtstart, date):
            dtstart = datetime.combine(dtstart, time())
        dtstart = dtstart.replace(tzinfo=UTC)
        rrstr = 'RRULE:%s' % element['RRULE'].to_ical().decode()
        rule = rrulestr(rrstr, dtstart=dtstart)

        # in some entries, tzinfo is missing
        if rule._until and rule._until.tzinfo is None:
            rule._until = rule._until.replace(tzinfo=UTC)
        rules.rrule(rule)

        exdates = element.get('exdate')
        if not isinstance(exdates, list):
            exdates = [exdates]
        for exdate in exdates:
            try:
                rules.exdate(exdate.dts[0].dt)
            except AttributeError:
                pass

        return rules.between(
            dtstart,
            (datetime.now() +
             relativedelta(months=int(recurring_month))).replace(tzinfo=UTC),
            inc=True)
    def get_rrule(self, dtstart):
        if self.complex_rule:
            d = dtstart.date()
            weekday = weekdays[d.weekday()]
            n = 1 + (d.day - 1) / 7

            start_day, days_in_month = calendar.monthrange(d.year, d.month)
            days_from_end = days_in_month - d.day

            minus_n = -1 - (days_from_end / 7)
            cr = (
                self.complex_rule.replace("%date%", dtstart.strftime("%Y%m%d"))
                .replace("%day%", dtstart.strftime("%d"))
                .replace("%month%", dtstart.strftime("%m"))
                .replace("%year%", dtstart.strftime("%Y"))
                .replace("%time%", dtstart.strftime("%H%M%S"))
                .replace("%datetime%", dtstart.strftime("%Y%m%dT%H%M%S"))
                .replace("%nthday%", "%s%s" % (n, weekday))
                .replace("%-nthday%", "%s%s" % (minus_n, weekday))
            )
            try:
                return rrule.rrulestr(str(cr), dtstart=dtstart)
            except ValueError:  # eg. unsupported property
                pass
        params = self.get_params()
        frequency = "rrule.%s" % self.frequency
        simple_rule = rrule.rrule(eval(frequency), dtstart=dtstart, **params)
        rs = rrule.rruleset()
        rs.rrule(simple_rule)
        return rs
Beispiel #5
0
def set_biz_calendar():
    #hk holidays
    holidays = [
        str2datetime('20150903'),
        str2datetime('20150928'),
        str2datetime('20151225'),
        str2datetime('20151226'),
        str2datetime('20150701'),
        str2datetime('20160101'),
        str2datetime('20160208'),
        str2datetime('20160209'),
        str2datetime('20160210'),
        str2datetime('20160325'),
        str2datetime('20160326'),
        str2datetime('20160328'),
        str2datetime('20160404'),
        str2datetime('20160502')
    ]

    r = rrule.rrule(
        rrule.DAILY,
        byweekday=[rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR],
        dtstart=str2datetime('20151201'))
    rs = rrule.rruleset()
    rs.rrule(r)
    for exdate in holidays:
        rs.exdate(exdate)

    return rs
        def __init__(self, event):
            self.event = event
            self.start = self.original_start = event["DTSTART"].dt
            self.end = self.original_end = self._get_event_end()
            self.exdates = []
            self.exdates_utc = set()
            exdates = event.get("EXDATE", [])
            for exdates in ((exdates,) if not isinstance(exdates, list) else exdates):
                for exdate in exdates.dts:
                    self.exdates.append(exdate.dt)
                    self.exdates_utc.add(self._unify_exdate(exdate.dt))
            self.rdates = []
            rdates = event.get("RDATE", [])
            for rdates in ((rdates,) if not isinstance(rdates, list) else rdates):
                for rdate in rdates.dts:
                    self.rdates.append(rdate.dt)
            
            self.make_all_dates_comparable()
            
            self.duration = self.end - self.start
            self.rule = rule = rruleset(cache=True)
            _rule = event.get("RRULE", None)
            if _rule:
                self.rrule = self.create_rule_with_start(_rule.to_ical().decode())
                rule.rrule(self.rrule)
            else:
                self.rrule = None

            for exdate in self.exdates:
                rule.exdate(exdate)
            for rdate in self.rdates:
                rule.rdate(rdate)
            rule.rdate(self.start)
Beispiel #7
0
    def get_due_date(self, now=None, periods=None):
        if now is None:
            now = datetime.now()
        if self.unit == 'hour':
            delta = timedelta(hours=self.length)
        elif self.unit == 'day':
            delta = timedelta(days=self.length)
        else:
            delta = None

        if self.due_at == 'period_end':
            start_date = now
            if delta:
                start_date += delta
                if self.unit == 'day':
                    start_date = start_date.date()
            end_dates = rruleset()
            for period in periods:
                end_dates.rrule(period.get_end_timestamps(start_date))

            if self.unit == 'hour' or self.unit == 'day':
                return end_dates[0]
            elif self.unit == 'period':
                length = self.length
                if (self.length > 0 and
                    not any(period.is_during_period(now) for period in periods)):
                    length -= 1
                return end_dates[length]
        else:
            if self.unit == 'hour' or self.unit == 'day':
                return now + delta
Beispiel #8
0
    def testTimeSequenceCalendar(self):
        from dateutil import rrule
        #import pdb

        interval = relativedelta(months=1,
                                 days=2,
                                 hours=3,
                                 minutes=13,
                                 seconds=27)
        n = 100
        timeseq1=map(ticks,[increment(self.stime1,interval,i) \
                            for i in range(n)])
        timeseq2 = time_sequence(self.stime1, interval, n)
        for t1, t2 in zip(timeseq1, timeseq2):
            self.assertEqual(t1, t2)

        test_cases = [("years", 1, rrule.YEARLY), ("months", 1, rrule.MONTHLY),
                      ("days", 7, rrule.WEEKLY), ("days", 1, rrule.DAILY),
                      ("hours", 1, rrule.HOURLY),
                      ("minutes", 1, rrule.MINUTELY),
                      ("seconds", 1, rrule.SECONDLY)]

        for (argname, argval, frequency) in test_cases:
            interval = relativedelta()
            setattr(interval, argname, argval)
            n = 100
            set = rrule.rruleset()
            set.rrule(rrule.rrule(frequency, dtstart=self.stime1, count=n))
            set.rdate(self.stime1)
            timeseq1 = list(set)
            timeseq1 = map(ticks, timeseq1)
            timeseq2 = time_sequence(self.stime1, interval, n)
            for t1, t2 in zip(timeseq1, timeseq2):
                self.assertEqual(t1, t2)
Beispiel #9
0
def _expand_rrule_all_day(rrule: str,
                          start: date,
                          exclusions: Iterable,
                          start_at: datetime,
                          end_at: datetime) -> Iterable[date]:
    """Expand an rrule for all-day events.

    To my mind, these events cannot have changes, just exclusions, because
    changes only affect the time, which doesn't exist for all-day events.
    """

    rules = rruleset()
    rules.rrule(rrulestr(rrule, dtstart=start, ignoretz=True))

    # add exclusions
    if exclusions:
        for xdate in exclusions:
            rules.exdate(datetime.combine(
                xdate.dts[0].dt, datetime.min.time()))

    dates = []
    # reduce start and end to datetimes without timezone that just represent a
    # date at midnight.
    for candidate in rules.between(
            datetime.combine(start_at.date(), datetime.min.time()),
            datetime.combine(end_at.date(), datetime.min.time()),
            inc=True):
        dates.append(candidate.date())
    return dates
Beispiel #10
0
def _recurring_component_to_events(component):
    """
    Given an icalendar component with an "RRULE"
    Return a list of events as dictionaries
    """
    rrule_as_str = component.get('rrule').to_ical()
    recur_rule = rrule.rrulestr(rrule_as_str,
                                dtstart=ensure_tzaware(component.decoded('dtstart')))
    recur_set = rrule.rruleset()
    recur_set.rrule(recur_rule)
    if 'exdate' in component:
        lines = component.decoded('exdate')
        if not hasattr(lines, '__iter__'):
            lines = [lines]
        for exdate_line in lines:
            for exdate in exdate_line.dts:
                recur_set.exdate(ensure_tzaware(exdate.dt))

    # get list of events in MAX_FUTURE days
    utcnow = now()
    later = utcnow + datetime.timedelta(days=MAX_FUTURE)
    start_times = recur_set.between(utcnow, later)

    # build list of events
    event_length = component.decoded('dtend') - component.decoded('dtstart')
    events = []
    for start in start_times:
        events.append({
            'start': start,
            'end': start + event_length,
            'summary': component.decoded('summary'),
            'uid': component.decoded('uid'),
            'last_modified': component.decoded('last-modified'),
        })
    return events
def get_early_closes(start, end):
    # TSX closed at 1:00 PM on december 24th.

    start = canonicalize_datetime(start)
    end = canonicalize_datetime(end)

    start = max(start, datetime(1993, 1, 1, tzinfo=pytz.utc))
    end = max(end, datetime(1993, 1, 1, tzinfo=pytz.utc))

    # Not included here are early closes prior to 1993
    # or unplanned early closes

    early_close_rules = []

    christmas_eve = rrule.rrule(
        rrule.MONTHLY,
        bymonth=12,
        bymonthday=24,
        byweekday=(rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR),
        cache=True,
        dtstart=start,
        until=end
    )
    early_close_rules.append(christmas_eve)

    early_close_ruleset = rrule.rruleset()

    for rule in early_close_rules:
        early_close_ruleset.rrule(rule)
    early_closes = early_close_ruleset.between(start, end, inc=True)

    early_closes.sort()
    return pd.DatetimeIndex(early_closes)
def calculate_rrule_exclusions(start_date, end_date, exclusion_commands, settings):
    exclusion_ruleset = rruleset()

    exclusion_types = exclusion_commands.exclusionList

    for exclusion_type in exclusion_types:

        if hasattr(exclusion_type, "exclusionRange"):
            from_date, _ = convert_date_time(exclusion_type.exclusionRange.fromDateTime, settings)
            to_date, _ = convert_date_time(exclusion_type.exclusionRange.toDateTime, settings)
            exclusion_ruleset.rrule(rrule(freq=DAILY, dtstart=from_date, until=to_date))

        elif hasattr(exclusion_type, "exclusionDateTime"):
            real_date, _ = convert_date_time(exclusion_type.exclusionDateTime, settings)
            exclusion_ruleset.rrule(rrule(freq=DAILY, dtstart=real_date, until=real_date))

        elif hasattr(exclusion_type, "exclusionMacro"):
            macro_value = exclusion_type.exclusionMacro
            exclusion_rule = EXCLUSION_MAP[macro_value]['rule'](start=start_date, end=end_date)
            exclusion_ruleset.rrule(exclusion_rule)
        else:
            # in that case, I have no idea what this is (the parser should have caught it) so just
            # raise an error or something
            raise UnknownExclusionTypeError

    matched_dates = list(exclusion_ruleset.between(after=start_date, before=end_date, inc=True))

    return len(matched_dates)
def do_timespans(command, settings):
    date_time, output_format = convert_date_time(command.dateTime, settings)

    # Note the very first date in case there is an exclusion rule
    first_date_time = date_time

    for operand in command.operandList:
        date_time = delta_arithmetic(date_time, operand)

    last_date_time = date_time

    # Make sure the dates are the right way around, or the
    # following functions will not work correctly.

    first_date_time, last_date_time = later_date_last(first_date_time, last_date_time)

    if hasattr(command, "exclusionCommands"):

        rules = rruleset()
        exclusion_rules = build_exclusion_list(command, first_date_time, last_date_time, settings)

        for rule in exclusion_rules:
            rules.rrule(rule)

        days_to_exclude = len(rules.between(first_date_time, last_date_time, True))
        operand = relativedelta(days=days_to_exclude)
        date_time += operand

    return date_time.strftime(output_format)
Beispiel #14
0
def next_working_date(date):
    from dateutil import rrule
    
    holidays = [
        datetime.date(2012, 5, 1,),
        datetime.date(2012, 6, 1,),
        # ...
    ]
    
    # Create a rule to recur every weekday starting today
    r = rrule.rrule(rrule.DAILY,
                    byweekday=[rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR],
                    dtstart=datetime.date.today())
    
    # Create a rruleset
    rs = rrule.rruleset()
    
    # Attach our rrule to it
    rs.rrule(r)
    
    # Add holidays as exclusion days
    for exdate in holidays:
        rs.exdate(exdate)
    
    return (rs[0])
Beispiel #15
0
    def test_timezone_serializing(self):
        """
        Serializing with timezones test
        """
        tzs = dateutil.tz.tzical("test_files/timezones.ics")
        pacific = tzs.get('US/Pacific')
        cal = base.Component('VCALENDAR')
        cal.setBehavior(icalendar.VCalendar2_0)
        ev = cal.add('vevent')
        ev.add('dtstart').value = datetime.datetime(2005,
                                                    10,
                                                    12,
                                                    9,
                                                    tzinfo=pacific)
        evruleset = rruleset()
        evruleset.rrule(
            rrule(WEEKLY,
                  interval=2,
                  byweekday=[2, 4],
                  until=datetime.datetime(2005, 12, 15, 9)))
        evruleset.rrule(rrule(MONTHLY, bymonthday=[-1, -5]))
        evruleset.exdate(datetime.datetime(2005, 10, 14, 9, tzinfo=pacific))
        ev.rruleset = evruleset
        ev.add('duration').value = datetime.timedelta(hours=1)

        # breaking date?
        #self.assertEqual(
        #    cal.serialize().replace('\r\n', '\n'),
        #    """BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\nBEGIN:VTIMEZONE\nTZID:US/Pacific\nBEGIN:STANDARD\nDTSTART:20001029T020000\nRRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\nTZNAME:PST\nTZOFFSETFROM:-0700\nTZOFFSETTO:-0800\nEND:STANDARD\nBEGIN:DAYLIGHT\nDTSTART:20000402T020000\nRRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4\nTZNAME:PDT\nTZOFFSETFROM:-0800\nTZOFFSETTO:-0700\nEND:DAYLIGHT\nEND:VTIMEZONE\nBEGIN:VEVENT\nUID:20150108T142459Z - 64333@testing-worker-linux-12-2-29839-linux-6-46319\n358\nDTSTART;TZID=US/Pacific:20051012T090000\nDURATION:PT1H\nEXDATE;TZID=US/Pacific:20051014T090000\nRRULE:FREQ=WEEKLY;BYDAY=WE,FR;INTERVAL=2;UNTIL=20051215T090000\nRRULE:FREQ=MONTHLY;BYMONTHDAY=-5,-1\nEND:VEVENT\nEND:VCALENDAR\n"""
        #)

        apple = tzs.get('America/Montreal')
        ev.dtstart.value = datetime.datetime(2005, 10, 12, 9, tzinfo=apple)
Beispiel #16
0
 def occurences(self):
     from dateutil import rrule
     r = rrule.rrule(rrule.WEEKLY, dtstart=self.dt_start,
                     until=self.dt_until)
     ruleset = rrule.rruleset()
     ruleset.rrule(r)
     return [Occurence(stamp, self) for stamp in ruleset]
Beispiel #17
0
 def update_buffer(self):
     """Update the 2-year date buffer."""
     if not self.recur_rule:
         return
     frequency = getattr(rrule, 
             self.recur_rule.get_frequency_display().upper())
     today = datetime.datetime.today()
     two_years_hence = today + datetime.timedelta(731)
     until = self.recur_rule.until or two_years_hence
     recur = rrule.rrule(frequency, dtstart=self.time, 
             interval=self.recur_rule.interval, until=until)
     recur_set = rrule.rruleset()
     recur_set.rrule(recur)
     for exclusion in self.recur_rule.exclusion_set.all():
         recur_set.exdate(exclusion.date)
     existing_tasks = Task.objects.filter(recur_rule=self.recur_rule)
     existing_dates = [task.time for task in existing_tasks]
     for task_date in recur_set:
         # don't re-create existing tasks
         if task_date in existing_dates:
             continue
         task = Task(job=self.job, time=task_date, hours=self.hours,
                 member=self.member, account=self.account, 
                 recur_rule=self.recur_rule)
         task.save()
def get_next_business_day(
    from_date: datetime.datetime,
    until_date: datetime.datetime,
    time_limit: Optional[datetime.time] = None,
    reverse: bool = False,
) -> datetime.date:
    rs = rrule.rruleset()
    weekdays = [rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR]
    weekenddays = (rrule.SA, rrule.SU)
    rs.rrule(
        rrule.rrule(
            rrule.DAILY, dtstart=from_date, until=until_date, byweekday=weekdays
        )
    )
    rs.exrule(
        rrule.rrule(
            rrule.WEEKLY, dtstart=from_date, until=until_date, byweekday=weekenddays
        )
    )
    rs = [rule.date() for rule in rs]  # type: ignore
    holidays_repository = HolidaysJsonRepository()
    holidays = holidays_repository.get_holidays(from_date.date(), until_date.date())
    rs = list(filter(lambda date: date not in holidays, rs))  # type: ignore
    next_business_day = rs[0] if not reverse else rs[-1]
    if from_date.date() in rs and time_limit and from_date.time() >= time_limit:
        next_business_day = rs[1] if not reverse else rs[-2]
    return next_business_day
Beispiel #19
0
    def rruleset(self):
        weekdays = []
        if self.monday:
            weekdays.append(MO)
        if self.tuesday: 
            weekdays.append(TU)
        if self.wednesday: 
            weekdays.append(WE)
        if self.thursday: 
            weekdays.append(TH)
        if self.friday: 
            weekdays.append(FR)
        if self.saturday: 
            weekdays.append(SA) 
        if self.sunday:    
            weekdays.append(SU) 

        rset = rruleset()
        dfrom = datetime.combine(self.from_date, datetime.min.time()).replace(tzinfo=tzutc())
        dto = datetime.combine(self.to_date, datetime.max.time()).replace(tzinfo=tzutc())
        
        rset.rrule(rrule(WEEKLY, dtstart=dfrom, until=dto, byweekday=weekdays))
        
        today = datetime.today()
        for d in DayOff.objects.filter(date__year=today.year):
            date = datetime.combine(d.date, datetime.min.time()).replace(tzinfo=tzutc())
            
            if self.days_off:
                rset.rdate(date)
            else:
                rset.exdate(date)
        
        return rset
Beispiel #20
0
    def save(self, *args, **kwargs):
        current_zone = timezone.get_default_timezone()

        # Set final date to the end, for one off events
        self.final_date = self.end

        # But find the last recurring event if possible
        if self.recurringevent_set.all():
            last_date = None

            # Recurring, find the last date
            for i in self.recurringevent_set.all():
                event_ruleset = rrule.rruleset()
                event_ruleset.rrule(i.rrule())

                # Add in any exclusions
                for j in self.recurringeventexclusion_set.all():
                    event_ruleset.exdate(timezone.make_naive(j.date, current_zone))

                try:
                    last_recurring_date = event_ruleset[-1]

                    if last_date is None or last_recurring_date > last_date:
                        last_date = last_recurring_date
                except IndexError:
                    pass

            if last_date:
                self.final_date = timezone.make_aware(last_date, current_zone)

        super(Event, self).save(*args, **kwargs)
Beispiel #21
0
def holidays(a=datetime.date.today(),
             b=datetime.date.today() + datetime.timedelta(days=365)):
    rs = rrule.rruleset()

    # Include all potential holiday observances
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=a,
                    until=b,
                    bymonth=12,
                    bymonthday=31,
                    byweekday=rrule.FR))  # New Years Day
    rs.rrule(
        rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth=1,
                    bymonthday=1))  # New Years Day
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=a,
                    until=b,
                    bymonth=1,
                    bymonthday=2,
                    byweekday=rrule.MO))  # New Years Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 1, byweekday= rrule.MO(3)))            # Martin Luther King Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 2, byweekday= rrule.MO(3)))            # Washington's Birthday
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, byeaster= -2))                                  # Good Friday
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 5, byweekday= rrule.MO(-1)))           # Memorial Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 7, bymonthday= 3, byweekday=rrule.FR)) # Independence Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 7, bymonthday= 4))                     # Independence Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 7, bymonthday= 5, byweekday=rrule.MO)) # Independence Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth= 9, byweekday= rrule.MO(1)))            # Labor Day
    # rs.rrule(rrule.rrule(rrule.YEARLY, dtstart=a, until=b, bymonth=11, byweekday= rrule.TH(4)))            # Thanksgiving Day
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=a,
                    until=b,
                    bymonth=12,
                    bymonthday=24,
                    byweekday=rrule.FR))  # Christmas
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=a,
                    until=b,
                    bymonth=12,
                    bymonthday=25))  # Christmas
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=a,
                    until=b,
                    bymonth=12,
                    bymonthday=26,
                    byweekday=rrule.MO))  # Christmas

    # Exclude potential holidays that fall on weekends
    rs.exrule(
        rrule.rrule(rrule.WEEKLY,
                    dtstart=a,
                    until=b,
                    byweekday=(rrule.SA, rrule.SU)))

    return rs
Beispiel #22
0
def _recurring_component_to_events(component):
    """
    Given an icalendar component with an "RRULE"
    Return a list of events as dictionaries
    """
    rrule_as_str = component.get('rrule').to_ical()
    recur_rule = rrule.rrulestr(rrule_as_str,
                                dtstart=component.decoded('dtstart'))
    recur_set = rrule.rruleset()
    recur_set.rrule(recur_rule)
    if 'exdate' in component:
        for exdate_line in component.decoded('exdate'):
            for exdate in exdate_line.dts:
                recur_set.exdate(exdate.dt)

    # get list of events in MAX_FUTURE days
    utcnow = now()
    later = utcnow + datetime.timedelta(days=MAX_FUTURE)
    start_times = recur_set.between(utcnow, later)

    # build list of events
    event_length = component.decoded('dtend') - component.decoded('dtstart')
    events = []
    for start in start_times:
        events.append({
            'start': start,
            'end': start + event_length,
            'summary': component.decoded('summary'),
            'uid': component.decoded('uid'),
            'last_modified': component.decoded('last-modified'),
        })
    return events
Beispiel #23
0
    def get_rrule(self, dtstart):
        if self.complex_rule:
            d = dtstart.date()
            weekday = weekdays[d.weekday()]
            n = 1 + (d.day - 1) / 7

            start_day, days_in_month = calendar.monthrange(d.year, d.month)
            days_from_end = days_in_month - d.day

            minus_n = -1 - (days_from_end / 7)
            cr = self.complex_rule \
                .replace("%date%", dtstart.strftime("%Y%m%d")) \
                .replace("%day%", dtstart.strftime("%d")) \
                .replace("%month%", dtstart.strftime("%m")) \
                .replace("%year%", dtstart.strftime("%Y")) \
                .replace("%time%", dtstart.strftime("%H%M%S")) \
                .replace("%datetime%", dtstart.strftime("%Y%m%dT%H%M%S")) \
                .replace("%nthday%", "%s%s" % (n, weekday)) \
                .replace("%-nthday%", "%s%s" % (minus_n, weekday))
            try:
                return rrule.rrulestr(str(cr), dtstart=dtstart)
            except ValueError:  # eg. unsupported property
                pass
        params = self.get_params()
        frequency = 'rrule.%s' % self.frequency
        simple_rule = rrule.rrule(eval(frequency), dtstart=dtstart, **params)
        rs = rrule.rruleset()
        rs.rrule(simple_rule)
        return rs
Beispiel #24
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
Beispiel #25
0
    def test_timezone_serializing():
        """
        Serializing with timezones test
        """
        tzs = dateutil.tz.tzical("test_files/timezones.ics")
        pacific = tzs.get('US/Pacific')
        cal = base.Component('VCALENDAR')
        cal.setBehavior(icalendar.VCalendar2_0)
        ev = cal.add('vevent')
        ev.add('dtstart').value = datetime.datetime(2005,
                                                    10,
                                                    12,
                                                    9,
                                                    tzinfo=pacific)
        evruleset = rruleset()
        evruleset.rrule(
            rrule(WEEKLY,
                  interval=2,
                  byweekday=[2, 4],
                  until=datetime.datetime(2005, 12, 15, 9)))
        evruleset.rrule(rrule(MONTHLY, bymonthday=[-1, -5]))
        evruleset.exdate(datetime.datetime(2005, 10, 14, 9, tzinfo=pacific))
        ev.rruleset = evruleset
        ev.add('duration').value = datetime.timedelta(hours=1)

        apple = tzs.get('America/Montreal')
        ev.dtstart.value = datetime.datetime(2005, 10, 12, 9, tzinfo=apple)
Beispiel #26
0
    def get_due_date(self, now=None, periods=None):
        if now is None:
            now = datetime.now()
        if self.unit == 'hour':
            delta = timedelta(hours=self.length)
        elif self.unit == 'day':
            delta = timedelta(days=self.length)
        else:
            delta = None

        if self.due_at == 'period_end':
            start_date = now
            if delta:
                start_date += delta
            end_dates = rruleset()
            for period in periods:
                end_dates.rrule(period.get_end_timestamps(start_date))

            if self.unit == 'hour' or self.unit == 'day':
                return end_dates[0]
            elif self.unit == 'period':
                return end_dates[self.length]
        else:
            if self.unit == 'hour' or self.unit == 'day':
                return now + delta
def get_early_closes(start, end):
    # TSX closed at 1:00 PM on december 24th.

    start = canonicalize_datetime(start)
    end = canonicalize_datetime(end)

    start = max(start, datetime(1993, 1, 1, tzinfo=pytz.utc))
    end = max(end, datetime(1993, 1, 1, tzinfo=pytz.utc))

    # Not included here are early closes prior to 1993
    # or unplanned early closes

    early_close_rules = []

    christmas_eve = rrule.rrule(rrule.MONTHLY,
                                bymonth=12,
                                bymonthday=24,
                                byweekday=(rrule.MO, rrule.TU, rrule.WE,
                                           rrule.TH, rrule.FR),
                                cache=True,
                                dtstart=start,
                                until=end)
    early_close_rules.append(christmas_eve)

    early_close_ruleset = rrule.rruleset()

    for rule in early_close_rules:
        early_close_ruleset.rrule(rule)
    early_closes = early_close_ruleset.between(start, end, inc=True)

    early_closes.sort()
    return pd.DatetimeIndex(early_closes)
Beispiel #28
0
    def test_timezone_serializing(self):
        """
        Serializing with timezones test
        """
        tzs = dateutil.tz.tzical("test_files/timezones.ics")
        pacific = tzs.get('US/Pacific')
        cal = base.Component('VCALENDAR')
        cal.setBehavior(icalendar.VCalendar2_0)
        ev = cal.add('vevent')
        ev.add('dtstart').value = datetime.datetime(2005, 10, 12, 9, tzinfo = pacific)
        evruleset = rruleset()
        evruleset.rrule(rrule(WEEKLY, interval=2, byweekday=[2,4], until=datetime.datetime(2005, 12, 15, 9)))
        evruleset.rrule(rrule(MONTHLY, bymonthday=[-1,-5]))
        evruleset.exdate(datetime.datetime(2005, 10, 14, 9, tzinfo = pacific))
        ev.rruleset = evruleset
        ev.add('duration').value = datetime.timedelta(hours=1)

        # breaking date?
        #self.assertEqual(
        #    cal.serialize().replace('\r\n', '\n'),
        #    """BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\nBEGIN:VTIMEZONE\nTZID:US/Pacific\nBEGIN:STANDARD\nDTSTART:20001029T020000\nRRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\nTZNAME:PST\nTZOFFSETFROM:-0700\nTZOFFSETTO:-0800\nEND:STANDARD\nBEGIN:DAYLIGHT\nDTSTART:20000402T020000\nRRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4\nTZNAME:PDT\nTZOFFSETFROM:-0800\nTZOFFSETTO:-0700\nEND:DAYLIGHT\nEND:VTIMEZONE\nBEGIN:VEVENT\nUID:20150108T142459Z - 64333@testing-worker-linux-12-2-29839-linux-6-46319\n358\nDTSTART;TZID=US/Pacific:20051012T090000\nDURATION:PT1H\nEXDATE;TZID=US/Pacific:20051014T090000\nRRULE:FREQ=WEEKLY;BYDAY=WE,FR;INTERVAL=2;UNTIL=20051215T090000\nRRULE:FREQ=MONTHLY;BYMONTHDAY=-5,-1\nEND:VEVENT\nEND:VCALENDAR\n"""
        #)

        apple = tzs.get('America/Montreal')
        ev.dtstart.value = datetime.datetime(2005, 10, 12, 9, tzinfo = apple)
Beispiel #29
0
 def _get_rruleset(self):
     self.ensure_one()
     ruleset = rruleset()
     if self.state != 'progress':
         return ruleset
     # set next_date which is used as the rrule 'dtstart' parameter
     next_date = self.start_date
     last_order = self.env['fsm.order'].search(
         [('fsm_recurring_id', '=', self.id),
          ('stage_id', '!=',
           self.env.ref('fieldservice.fsm_stage_cancelled').id)],
         offset=0,
         limit=1,
         order='scheduled_date_start desc')
     if last_order:
         next_date = last_order.scheduled_date_start
     # set thru_date to use as rrule 'until' parameter
     days_ahead = self.fsm_frequency_set_id.schedule_days
     request_thru_date = datetime.now() + relativedelta(days=+days_ahead)
     if self.end_date and (self.end_date < request_thru_date):
         thru_date = self.end_date
     else:
         thru_date = request_thru_date
     # use variables to calulate and return the rruleset object
     ruleset = self.fsm_frequency_set_id._get_rruleset(dtstart=next_date,
                                                       until=thru_date)
     return ruleset
Beispiel #30
0
 def _rule_set(self, dtstart):
     rule = rrule.rrulestr(self.repeat_rule, dtstart=dtstart)
     rule_set = rrule.rruleset()
     rule_set.rrule(rule)
     for exdate in self.exception_dates:
         rule_set.exdate(exdate)
     return rule_set
Beispiel #31
0
def get_events_from_rrule(ical_event, event_template, start_date, end_date):
    events = []

    ical_rrule = ical_event.get('rrule')
    ical_rrule_str = ical_rrule.to_ical().decode('utf-8')
    rrule = rrulestr(ical_rrule_str,
                     ignoretz=True,
                     dtstart=start_date.replace(tzinfo=None))
    ruleset = rruleset()
    ruleset.rrule(rrule)

    exdates = get_exdates(ical_event)
    for exdate in exdates:
        for exdate_date in exdate.dts:
            ruleset.exdate(exdate_date.dt.replace(tzinfo=None))

    after = datetime.utcnow() - timedelta(**INTO_PAST)
    before = datetime.utcnow() + timedelta(**INTO_FUTURE)
    rrule_instances = list(ruleset.between(after, before))
    for num, rrule_instance in enumerate(rrule_instances, start=1):
        event = copy(event_template)
        event['uid'] = "{}-{}".format(event_template['uid'], num)
        event['start'] = berlin.localize(rrule_instance).isoformat()

        if not event["allDay"]:
            instance_end_date = datetime(rrule_instance.year,
                                         rrule_instance.month,
                                         rrule_instance.day, end_date.hour,
                                         end_date.minute, end_date.second)
            event["end"] = berlin.localize(instance_end_date).isoformat()
        print(repr(event))
        events.append(event)

    return events
Beispiel #32
0
 def setRuleFromDateUtil(self, ruleSetOrRule):
     """Extract rules and dates from ruleSetOrRule, set them in self.
     
     If a dateutil.rrule.rrule is passed in instead of an rruleset, treat
     it as the new rruleset.
     
     """
     if isinstance(ruleSetOrRule, rrule):
         set = rruleset()
         set.rrule(ruleSetOrRule)
         ruleSetOrRule = set
     elif not isinstance(ruleSetOrRule, rruleset):
         raise TypeError, "ruleSetOrRule must be an rrule or rruleset"
     for rtype in 'rrule', 'exrule':
         rules = getattr(ruleSetOrRule, '_' + rtype, [])
         if rules is None: rules = []
         itemlist = []
         for rule in rules:
             ruleItem = RecurrenceRule(parent=self)
             ruleItem.setRuleFromDateUtil(rule)
             itemlist.append(ruleItem)
         setattr(self, rtype + 's', itemlist)
     for typ in 'rdate', 'exdate':
         # While most dates are naive, strip tzinfo off
         naive = [stripTZ(e) for e in getattr(ruleSetOrRule, '_' + typ, [])]
         setattr(self, typ + 's', naive)
Beispiel #33
0
def get_number_of_hours_between_dates(
    d1, d2, skip_weekends=True, list_public_holidays=False, hours_range=range(0,23), granularity=12
):
    def convert_days_from_hours(hours, granularity, hours_per_day):
        return int(hours/granularity)*granularity/hours_per_day
    rules = rrule.rruleset()
    
    byweekday_list = [rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR]
    if not skip_weekends:
        byweekday_list.extend([rrule.SA, rrule.SU])
    
    rules.rrule(
        rrule.rrule(
            freq=rrule.HOURLY,
            byweekday=byweekday_list,
            byhour=hours_range,
            dtstart=d1,
            until=d2,
        )
    )
    if list_public_holidays:
        for holiday in list_public_holidays:
            s1 = datetime(holiday.year, holiday.month, holiday.day, 0, 0, 0)
            s2 = datetime(holiday.year, holiday.month, holiday.day, 23, 59, 59)
            rules.exrule(
                rrule.rrule(
                    rrule.HOURLY,
                    dtstart=s1,
                    until=s2
                )
            )
    dates = defaultdict(int)
    for r in list(rules):
        dates[r.date()] += 1
    return {k: convert_days_from_hours(v, granularity, len(hours_range)) for k, v in dates.items()}
Beispiel #34
0
def parse_rrule(component, tz=UTC):
    """
    Extract a dateutil.rrule object from an icalendar component. Also includes
    the component's dtstart and exdate properties. The rdate and exrule
    properties are not yet supported.
    
    :param component: icalendar component
    :param tz: timezone for DST handling
    :return: extracted rrule or rruleset
    """
    if component.get('rrule'):
        # component['rrule'] can be both a scalar and a list
        rrules = component['rrule']
        if not isinstance(rrules, list):
            rrules = [rrules]

        # Since DTSTART are always made timezone aware, UNTIL with no tzinfo
        # must be converted to UTC.
        for rule in rrules:
            until = rule.get("until")
            for idx, dt in enumerate(until or []):
                if not hasattr(dt, 'tzinfo'):
                    until[idx] = normalize(normalize(dt, tz=tz), tz=UTC)

        # Parse the rrules, might return a rruleset instance, instead of rrule
        rule = rrulestr('\n'.join(x.to_ical().decode() for x in rrules),
                        dtstart=normalize(component['dtstart'].dt, tz=tz))

        if component.get('exdate'):
            # Make sure, to work with a rruleset
            if isinstance(rule, rrule):
                rules = rruleset()
                rules.rrule(rule)
                rule = rules

            # Add exdates to the rruleset
            for exd in extract_exdates(component):
                rule.exdate(exd)

        #TODO: What about rdates and exrules?

    # You really want an rrule for a component without rrule? Here you are.
    else:
        rule = rruleset()
        rule.rdate(normalize(component['dtstart'].dt, tz=tz))

    return rule
Beispiel #35
0
def convert_rdates(dates: List[datetime]):
    rrules = rruleset()
    dates.sort()
    rrules.rrule(
        rrule(YEARLY, count=1, dtstart=dates.pop(0).replace(tzinfo=None)))
    for dt in dates:
        rrules.rdate(dt.replace(tzinfo=None))
    return [rrules]
Beispiel #36
0
def _default_ruleset():
    '''Return a datetime.rrule.rruleset object that excludes weekends.'''
    dates = rrule.rruleset()
    # exclude weekends
    dates.rrule(rrule.rrule(rrule.DAILY, byweekday=( rrule.MO, rrule.TU,
                                                     rrule.WE, rrule.TH,
                                                     rrule.FR, )))
    return dates
Beispiel #37
0
def NYSE_tradingdays(a, b):
    rs = rrule.rruleset()
    rs.rrule(rrule.rrule(rrule.DAILY, dtstart=a, until=b))
    # Exclude weekends and holidays
    rs.exrule(
        rrule.rrule(rrule.WEEKLY, dtstart=a, byweekday=(rrule.SA, rrule.SU)))
    rs.exrule(NYSE_holidays(a, b))
    return rs
def init_rruleset():
    rr = rruleset()
    rr.rrule(rrule(DAILY,
                   byweekday=(MO,TU,WE,TH,FR),
                   dtstart=datetime.datetime(2010,1,1)))
    for h in holidays:
        rr.exdate(h)
    return rr
Beispiel #39
0
 def rruleset(self, dtstart):
     set_ = rruleset(**self._rruleset())
     for rule in self.rules:
         if not rule.exclusive:
             set_.rrule(rule.rrule(dtstart))
         else:
             set_.exrule(rule.rrule(dtstart))
     return set_
Beispiel #40
0
def get_events(url):
    req = urllib.request.Request(url)
    res = urllib.request.urlopen(req)
    data = res.read()
    cal = icalendar.Calendar.from_ical(data)
    events = []
    for event in cal.walk('vevent'):
        start = event.get('dtstart')
        if not start:
            continue
        start = start.dt
        if (type(start) == date):
            start = tz.localize(datetime.combine(start, datetime.min.time()))
        end = event.get('dtend')
        if not end:
            continue
        end = end.dt
        if (type(end) == date):
            end = tz.localize(datetime.combine(end, datetime.max.time()))

        repeat = event.get('rrule')
        if repeat:
            rrule = rrulestr(repeat.to_ical().decode(),
                             ignoretz=True,
                             dtstart=start.replace(tzinfo=None))
            ruleset = rruleset()
            ruleset.rrule(rrule)
            nextRepeat = ruleset.between(recurFrom, recurTo)
            if (len(nextRepeat) == 0):
                continue
            start = tz.localize(nextRepeat[0])
            end = tz.localize(
                datetime(nextRepeat[0].year, nextRepeat[0].month,
                         nextRepeat[0].day, end.hour, end.minute, end.second))

        if (end < now):
            continue

        events.append({
            'start': start,
            'end': end,
            'summary': event.get('summary'),
            'location': event.get('location'),
        })

    events.sort(key=lambda x: x['start'])
    currentEvents = []
    nextEvent = None
    for event in events:
        if (event['start'] < now and event['end'] > now):
            currentEvents.append(clean_event(event))
        if (event['start'] > now):
            nextEvent = event
            break
    return {
        'current': currentEvents,
        'next': clean_event(nextEvent),
    }
Beispiel #41
0
def get_working_days(a, b):
    rs = rrule.rruleset()
    rs.rrule(rrule.rrule(rrule.DAILY, dtstart=a,
                         until=b))  # Get all days between a and b
    rs.exrule(
        rrule.rrule(rrule.WEEKLY, dtstart=a,
                    byweekday=(rrule.SA, rrule.SU)))  # Exclude weekends
    rs.exrule(get_holidays(a, b))  # Exclude holidays
    return rs
Beispiel #42
0
def init_rruleset():
    rr = rruleset()
    rr.rrule(
        rrule(DAILY,
              byweekday=(MO, TU, WE, TH, FR),
              dtstart=datetime.datetime(2010, 1, 1)))
    for h in holidays:
        rr.exdate(h)
    return rr
Beispiel #43
0
def get_opex_friday(start, end):
    rules = []
    opex_day = rrule.rrule(rrule.MONTHLY, byweekday=(rrule.FR(+3)), cache=True, dtstart=start, until=end)
    rules.append(opex_day)
    ruleset = rrule.rruleset()
    for rule in rules:
        ruleset.rrule(rule)
    days = ruleset.between(start, end, inc=True)
    return days
 def _get_rruleset(self, dtstart=None, until=None):
     self.ensure_one()
     rset = rruleset()
     for rule in self.fsm_frequency_ids:
         if not rule.is_exclusive:
             rset.rrule(rule._get_rrule(dtstart, until))
         else:
             rset.exrule(rule._get_rrule(dtstart))
     return rset
Beispiel #45
0
def parse_rrule(component, tz=UTC):
    """
    Extract a dateutil.rrule object from an icalendar component. Also includes
    the component's dtstart and exdate properties. The rdate and exrule
    properties are not yet supported.

    :param component: icalendar component
    :param tz: timezone for DST handling
    :return: extracted rrule or rruleset
    """
    if component.get('rrule'):
        # component['rrule'] can be both a scalar and a list
        rrules = component['rrule']
        if not isinstance(rrules, list):
            rrules = [rrules]

        # If dtstart is a datetime, make sure it's in a timezone.
        rdtstart = component['dtstart'].dt
        if type(rdtstart) is datetime:
            rdtstart = normalize(rdtstart, tz=tz)

        # Parse the rrules, might return a rruleset instance, instead of rrule
        rule = rrulestr('\n'.join(x.to_ical().decode() for x in rrules),
                        dtstart=rdtstart)

        if component.get('exdate'):
            # Make sure, to work with a rruleset
            if isinstance(rule, rrule):
                rules = rruleset()
                rules.rrule(rule)
                rule = rules

            # Add exdates to the rruleset
            for exd in extract_exdates(component):
                rule.exdate(exd)

        # TODO: What about rdates and exrules?

    # You really want an rrule for a component without rrule? Here you are.
    else:
        rule = rruleset()
        rule.rdate(normalize(component['dtstart'].dt, tz=tz))

    return rule
Beispiel #46
0
def add_meeting_to_vcal(ical, meeting, reminder=None):
    """ Convert a Meeting object into iCal object and add it to the
    provided calendar.

    :arg ical: the iCal calendar object to which the meetings should
        be added.
    :arg meeting: a single fedocal.model.Meeting object to convert to
        iCal and add to the provided calendar.
    :kwarg reminder: None or a datetime.timedelta instance.
    """
    entry = ical.add('vevent')
    entry.add('summary').value = meeting.meeting_name
    if meeting.meeting_information:
        entry.add('description').value = meeting.meeting_information
    entry.add('organizer').value = ', '.join(meeting.meeting_manager)
    if meeting.meeting_location:
        entry.add('location').value = meeting.meeting_location

    start = entry.add('dtstart')
    stop = entry.add('dtend')
    if meeting.full_day:
        start.value = meeting.meeting_date
        stop.value = meeting.meeting_date_end
        entry.add('transp').value = 'TRANSPARENT'
    else:
        tz = zoneinfo.gettz(meeting.meeting_timezone)

        dti_start = datetime.combine(
            meeting.meeting_date, meeting.meeting_time_start)
        start.value = dti_start.replace(tzinfo=tz)

        dti_end = datetime.combine(
            meeting.meeting_date_end, meeting.meeting_time_stop)
        stop.value = dti_end.replace(tzinfo=tz)

    if meeting.recursion_frequency and meeting.recursion_ends:
        newrule = rrule.rruleset()
        freq = 1
        if meeting.recursion_frequency == 14:
            freq = 2
        newrule.rrule(
            rrule.rrule(
                freq=rrule.WEEKLY,
                interval=freq,
                dtstart=start.value,
                until=meeting.recursion_ends))
        entry.rruleset = newrule

    if reminder:
        valarm = entry.add('valarm')
        valarm.add('trigger').value = reminder
        valarm.add('action').value = 'DISPLAY'
        valarm.add('description').value = (
            '[{calendar_name}] [Fedocal] Reminder meeting: {meeting_name}'
        ).format(calendar_name=meeting.calendar_name,
                 meeting_name=meeting.meeting_name)
Beispiel #47
0
def test_compare_rrule_diff():
    first = iCalendar()
    first_vevent = first.add('vevent')
    first_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    rset = rrule.rruleset()
    rset.rrule(rrule.rrule(freq=rrule.DAILY, count=3))
    first_vevent.rruleset = rset

    second = iCalendar()
    second_vevent = second.add('vevent')
    second_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    second_out = iCalendar()
    rset = rrule.rruleset()
    rset.rrule(rrule.rrule(freq=rrule.DAILY, count=4))
    second_vevent.rruleset = rset

    compare(first, second, second_out)
    assert len(first.contents) == 1
    assert len(second_out.contents) == 1
Beispiel #48
0
 def createDateUtilFromRule(self, dtstart):
     """Return an appropriate dateutil.rrule.rruleset."""
     ruleset = rruleset()
     for rtype in 'rrule', 'exrule':
         for rule in getattr(self, rtype + 's', []):
             getattr(ruleset, rtype)(rule.createDateUtilFromRule(dtstart))
     for datetype in 'rdate', 'exdate':
         for date in getattr(self, datetype + 's', []):
             getattr(ruleset, datetype)(date)
     return ruleset
Beispiel #49
0
 def createDateUtilFromRule(self, dtstart):
     """Return an appropriate dateutil.rrule.rruleset."""
     ruleset = rruleset()
     for rtype in 'rrule', 'exrule':
         for rule in getattr(self, rtype + 's', []):
             getattr(ruleset, rtype)(rule.createDateUtilFromRule(dtstart))
     for datetype in 'rdate', 'exdate':
         for date in getattr(self, datetype + 's', []):
             getattr(ruleset, datetype)(date)
     return ruleset
Beispiel #50
0
def thanksgiving(start=date.today(), end=date.today() + timedelta(days=365)):
    ''' Example for one date. '''
    rs = rrule.rruleset()
    rs.rrule(
        rrule.rrule(rrule.YEARLY,
                    dtstart=start,
                    until=end,
                    bymonth=11,
                    byweekday=rrule.TH(4)))
    return rs
Beispiel #51
0
def ical_feed(request):
    # We need an appropriate hostname
    if Site._meta.installed:
        current_site = Site.objects.get_current()
    else:
        current_site = RequestSite(request)

    # Calendar object with various settings needed
    cal = vobject.iCalendar()

    cal.add('X-WR-TIMEZONE').value = settings.TIME_ZONE
    cal.add('X-WR-CALNAME').value = 'Events'
    cal.add('X-WR-CALDESC').value = 'Events Calendar'
    cal.add('CALSCALE').value = 'GREGORIAN'

    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this

    # Events
    for event in Event.objects.all().prefetch_related('recurringevent_set', 'recurringeventexclusion_set'):
        if event.recurringevent_set.all():
            # Recurring event
            for i in event.recurringevent_set.all():
                v = cal.add('vevent')

                v.add('uid').value = 'recurring-event-%d@%s' % (i.id, current_site)
                v.add('summary').value = event.title

                v.add('dtstart').value = event.start
                v.add('dtend').value = event.end

                event_ruleset = rrule.rruleset()
                event_ruleset.rrule(i.rrule())

                # Add in any exclusions
                for j in event.recurringeventexclusion_set.all():
                    event_ruleset.exdate(j.date)

                v.rruleset = event_ruleset
        else:
            # One off event
            v = cal.add('vevent')

            v.add('uid').value = 'event-%d@%s' % (event.id, current_site)
            v.add('summary').value = event.title

            v.add('dtstart').value = event.start
            v.add('dtend').value = event.end

    icalstream = cal.serialize()

    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Filename'] = 'events.ics'  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=events.ics'

    return response
Beispiel #52
0
def get_start_times(event, start=None, end=None):
    # Expands the rrule on event to return a list of arrow datetimes
    # representing start times for its recurring instances.
    # If start and/or end are supplied, will return times within that range,
    # otherwise defaults to the event start date and now + 1 year;
    # this can return a lot of instances if the event recurs more frequently
    # than weekly!

    if isinstance(event, RecurringEvent):
        # Localize first so that expansion covers DST
        if event.start_timezone:
            event.start = event.start.to(event.start_timezone)

        if not start:
            start = event.start
        else:
            start = arrow.get(start)
        if not end:
            end = arrow.utcnow().replace(years=+EXPAND_RECURRING_YEARS)
        else:
            end = arrow.get(end)

        rrules = parse_rrule(event)
        if not rrules:
            log.warn('Tried to expand a non-recurring event',
                     event_id=event.id)
            return [event.start]

        excl_dates = parse_exdate(event)

        if len(excl_dates) > 0:
            if not isinstance(rrules, rruleset):
                rrules = rruleset().rrule(rrules)

            # We want naive-everything for all-day events.
            if event.all_day:
                excl_dates = map(lambda x: x.naive, excl_dates)
            map(rrules.exdate, excl_dates)

        # Return all start times between start and end, including start and
        # end themselves if they obey the rule.
        if event.all_day:
            # compare naive times, since date handling in rrulestr is naive
            # when UNTIL takes the form YYYYMMDD
            start = start.to('utc').naive
            end = end.to('utc').naive

        start_times = rrules.between(start, end, inc=True)

        # Convert back to UTC, which covers daylight savings differences
        start_times = [arrow.get(t).to('utc') for t in start_times]

        return start_times

    return [event.start]
 def __init__(self):
     BaseCalendarTest.__init__(self)
     self.cal = Calendar(workdays=[0,1,4,6])
     rr = rruleset()
     rr.rrule(rrule(DAILY,
                    byweekday=(MO,TU,FR,SU),
                    dtstart=datetime.datetime(2010,1,1)))
     self.rr = rr
     self.dates = rr.between(datetime.datetime(2010,1,1),
                             datetime.datetime(2013,12,31),
                             inc=True)
Beispiel #54
0
def workday_count(alpha, omega):
    """
    Расчёт рабочих дней с учетов выходных.

    """
    dates = rrule.rruleset()  # create an rrule.rruleset instance
    dates.rrule(rrule.rrule(DAILY, dtstart=alpha, until=omega))  # this set is INCLUSIVE of alpha and omega
    dates.exrule(rrule.rrule(DAILY,
                             byweekday=(rrule.SA, rrule.SU),
                             dtstart=alpha))  # here's where we exclude the weekend dates
    return len(list(dates))  # there's probably a faster way to handle this
 def set_recurrence_from_string(self, rrule_data):
     """ rrule_data is a string representing one or several rule in
     iCalendar format
     """
     rrule_temp = rrulestr(rrule_data, forceset=True,
         dtstart=self.start_datetime)
     if isinstance(rrule_temp, rruleset):
         self._recurrence = rrule_temp
     else: # rrule
         self._recurrence = rruleset()
         self._recurrence.rrule(rrule_temp)
     return self._recurrence
Beispiel #56
0
def days(start, stop):
    """
    Return days between start & stop (inclusive)
    
    Note that start must be less than stop or else 0 is returned.
    
    @param start: Start date
    @param stop: Stop date
    @return int
    """
    dates=rrule.rruleset()
    # Get dates between start/stop (which are inclusive)
    dates.rrule(rrule.rrule(rrule.DAILY, dtstart=start, until=stop))
    return dates.count()
 def __init__(self):
     BaseCalendarTest.__init__(self)
     self.holidays = [parse(x) for x in global_holidays.split('\n')]
     self.cal = Calendar(workdays=[0], holidays=self.holidays)
     rr = rruleset()
     rr.rrule(rrule(DAILY,
                    byweekday=(MO),
                    dtstart=datetime.datetime(2010,1,1)))
     for h in self.holidays:
         rr.exdate(h)
     self.rr = rr
     self.dates = rr.between(datetime.datetime(2010,1,1),
                             datetime.datetime(2013,12,31),
                             inc=True)
Beispiel #58
0
def passed_weekdays():

    today = date.today()

    # Use dateutils ruleset to count the number of working days (we are
    # definging that as mon-fri) between two dates.
    dates = rrule.rruleset()
    dates.rrule(rrule.rrule(rrule.DAILY, dtstart=THE_BEGINNING_OF_TIME, until=today))
    dates.exrule(rrule.rrule(rrule.DAILY, byweekday=(rrule.SA, rrule.SU), dtstart=THE_BEGINNING_OF_TIME))
    #This is includive of start and end dates - so to normalise and make it
    # the same as the daily calcs, remove one.
    passed_weekdays = dates.count() - 1

    return passed_weekdays
Beispiel #59
0
 def rruleset(self):
     if self.start is None:
         return None
     rrs = rruleset(cache=True)
     if self.frequency is not None:
         rrs.rrule(self.build_rrule())
     elif not self.rdates:
         # no rules or rdates, nothing to do
         return None
     for dt in self.rdates:
         rrs.rdate(dt)
     for dt in self.exdates:
         rrs.exdate(dt)
     return rrs
 def set_recurrence(self, rrule_data):
     """ rrule_data can be either a rrule, a rruleset or a string
     reprensenting one or several rrule in iCalendar format
     """
     if isinstance(rrule_data, rruleset):
         self._recurrence = rrule_data
     elif isinstance(rrule_data, rrule):
         self._recurrence = rruleset()
         self._recurrence.rrule(rrule_data)
     elif isinstance(rrule_data, basestring):
         self.set_recurrence_from_string(rrule_data)
     else:
         raise TypeError, "don't know how to handle provided "\
                          "recurrence infos"
     return self._recurrence