It is often useful to know what the next occurrence is given a list of
        events.  This function produces a generator that yields the
        the most recent occurrence after the date ``after`` from any of the
        events in ``self.events``
962473
def occurrences_after(self, after=None):
        
        from schedule.models import Occurrence

        if after is None:
            after = timezone.now()
        occ_replacer = OccurrenceReplacer(
            Occurrence.objects.filter(event__in=self.events))
        generators = [event._occurrences_after_generator(after) for event in self.events]
        occurrences = []

        for generator in generators:
            try:
                heapq.heappush(occurrences, (next(generator), generator))
            except StopIteration:
                pass

        while occurrences:
            generator = occurrences[0][1]

            try:
                next_occurrence = heapq.heapreplace(occurrences, (next(generator), generator))[0]
            except StopIteration:
                next_occurrence = heapq.heappop(occurrences)[0]
            yield occ_replacer.get_occurrence(next_occurrence)
1122847
def events(self):
        
        if self._events is None:
            self._events = self.parent.calendar.events(
                calendarId="primary", singleEvents=True, orderBy="startTime",
                timeMin=self.since, timeMax=self.until)
        return self._events
860855
def next_occurrence(from = nil, options = {})
      from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time)
      enumerate_occurrences(from + 1, nil, options).next
    rescue StopIteration
      nil
    end
450293
def daily_occurrences(self, dt=None):
        '''
        
        '''
        return Occurrence.objects.daily_occurrences(dt=dt, event=self)
1074550
def get_next_occurrence(tx: ScheduledTransaction) -> date:
    
    # Reference documentation:
    # https://github.com/MisterY/gnucash-portfolio/issues/3

    # Preparing ref day is an important part before the calculation.
    # It should be:
    #   a) the last occurrence date + 1, or
    #   b) the recurrence start date - 1.
    # because the refDate is the date from which the due dates are being calculated. To include
    # the ones starting today, we need to calculate from the day before.
    ref_datum: Datum = Datum()
    if tx.last_occur:
        #ref_datum.set_value(tx.last_occur)
        ref_datum.from_date(tx.last_occur)
        ref_datum.add_days(1)
    else:
        ref_datum.from_date(tx.recurrence.recurrence_period_start)
        ref_datum.subtract_days(1)
    ref_date: datetime = ref_datum.value

    # today = datetimeutils.today_date()
    #today = Datum().today()
    # skipped schedule
    #if ref_date > today: 
    #    ref_date = today

    ###########################################################
    # The code below mimics the function
    # recurrenceNextInstance(const Recurrence *r, const GDate *refDate, GDate *nextDate)
    # https://github.com/Gnucash/gnucash/blob/115c0bf4a4afcae4269fe4b9d1e4a73ec7762ec6/libgnucash/engine/Recurrence.c#L172

    start_date: Datum = Datum()
    #start_date: datetime = tx.recurrence.recurrence_period_start
    start_date.from_date(tx.recurrence.recurrence_period_start)
    if ref_date < start_date.value:
        # If the occurrence hasn't even started, the next date is the start date.
        # this should also handle the "once" type in most cases.
        return start_date.value.date()

    # start at refDate.
    next_date: Datum = Datum()
    # next_date: datetime = ref_date
    next_date.from_datetime(ref_date)

    # last_date: datetime = tx.last_occur
    # print(tx.name, base_date, tx.recurrence.recurrence_period_start,
    #       tx.recurrence.recurrence_mult, tx.recurrence.recurrence_period_type)

    # /* Step 1: move FORWARD one period, passing exactly one occurrence. */

    mult: int = tx.recurrence.recurrence_mult
    period: str = tx.recurrence.recurrence_period_type
    wadj = tx.recurrence.recurrence_weekend_adjust

    # Not all periods from the original file are included at the moment.
    if period in ([RecurrencePeriod.YEAR.value, RecurrencePeriod.MONTH.value,
                   RecurrencePeriod.END_OF_MONTH.value]):
        if period == RecurrencePeriod.YEAR.value:
            mult *= 12

        # handle weekend adjustment here.
        ## Takes care of short months.
        # next_weekday = datetimeutils.get_day_name(next_date)
        next_weekday = next_date.get_day_name()
        if wadj == WeekendAdjustment.BACK.value and (
                period in ([RecurrencePeriod.YEAR.value, RecurrencePeriod.MONTH.value,
                            RecurrencePeriod.END_OF_MONTH.value]) and
                (next_weekday == "Saturday" or next_weekday == "Sunday")):
            # "Allows the following Friday-based calculations to proceed if 'next'
            #  is between Friday and the target day."
            days_to_subtract = 1 if next_weekday == "Saturday" else 2

            # next_date = datetimeutils.subtract_days(next_date, days_to_subtract)
            next_date.subtract_days(days_to_subtract)

        if wadj == WeekendAdjustment.BACK.value and (
                period in ([RecurrencePeriod.YEAR.value, RecurrencePeriod.MONTH.value,
                            RecurrencePeriod.END_OF_MONTH.value]) and next_weekday == "Friday"):
            next_date = handle_friday(next_date, period, mult, start_date)

        # Line 274.
        temp_date = next_date.clone()
        if (temp_date.is_end_of_month() or
                (period in [RecurrencePeriod.MONTH.value, RecurrencePeriod.YEAR.value]
                 and (next_date.get_day() >= start_date.get_day()))
           ):
            # next_date = datetimeutils.add_months(next_date, mult)
            next_date.add_months(mult)
            # Set at end of month again (?!)
            #next_date = datetimeutils.get_end_of_month(next_date)
        else:
            # one fewer month fwd because of the occurrence in this month.
            next_date.add_months(mult - 1)

    # elif period == "once":
    #     next_date = tx.recurrence.recurrence_period_start

    elif period == RecurrencePeriod.DAY.value:
        logging.warning("daily not handled")

    else:
        logging.info(f"recurrence not handled: {period}")

    #######################
    # Step 2
    # "Back up to align to the base phase. To ensure forward
    # progress, we never subtract as much as we added (x % mult < mult)"

    if period in ([RecurrencePeriod.YEAR.value, RecurrencePeriod.MONTH.value,
                   RecurrencePeriod.END_OF_MONTH.value]):
        n_months = (
            12 * (next_date.get_year() - start_date.get_year()) +
            (next_date.get_month() - start_date.get_month())
        )
        next_date.subtract_months(n_months % mult)

        # dim
        days_in_month = datetimeutils.get_days_in_month(
            next_date.get_year(), next_date.get_month())

        # Handle adjustment for 3 ways.
        if (period == RecurrencePeriod.END_OF_MONTH.value or
                next_date.get_day() >= days_in_month):
            # Set to last day of the month.
            next_date.set_day(days_in_month)
        else:
            # Same day as the start.
            next_date.set_day(start_date.get_day())

        # Adjust for dates on the weekend.
        if (period == RecurrencePeriod.YEAR.value or period == RecurrencePeriod.MONTH.value or
                period == RecurrencePeriod.END_OF_MONTH.value):
            weekday = next_date.get_day_name()
            if weekday == "Saturday" or weekday == "Sunday":
                if wadj == WeekendAdjustment.BACK.value:
                    next_date.subtract_days(1 if weekday == "Saturday" else 2)
                elif wadj == WeekendAdjustment.FORWARD.value:
                    next_date.add_days(2 if weekday == "Saturday" else 1)

    return next_date.value.date()
908878
def next_trials(self):
        
        trials = []

        for trial in self._trial_generator:
            if trial is None:
                return trials
            trials += [trial]

        self._finished = True
        return trials
80107
def currentEvent(self):
        '''
        
        '''
        currentEvent =  self.recentEvents.filter(endTime__gte=timezone.now()).order_by('startTime').first()
        if not currentEvent:
            currentEvent = self.recentEvents.filter(
                endTime__lte=timezone.now()
            ).order_by('-endTime').first()
        return currentEvent
221010
function after(results, next) {
    item.trigger('after:' + method, function done(error) {
      next(error, results);
    });
  }
333168
def with_upcoming_occurrences(self):
        
        return self.filter(
            Q(is_drop_in=False, occurrences__start__gte=djtz.now) |
            Q(Q(is_drop_in=True) | Q(occurrences__is_all_day=True), occurrences__end__gt=djtz.now)
        )
713210
def occurrence_at( time )
      real_duration = duration - 1

      range = [ time - real_duration, time ]

      start_time = proxy.occurrences_between( range[0], range[1] ).first
      end_time   = start_time + real_duration

      Occurrence.new start_time, real_duration, end_time
    end
17980
def recentEvents(self):
        '''
        
        '''
        return Event.objects.filter(
            Q(pk__in=self.individualEvents.values_list('pk',flat=True)) |
            Q(session__in=self.eventSessions.all()) |
            Q(publicevent__category__in=self.eventCategories.all()) |
            Q(series__category__in=self.seriesCategories.all())
        ).filter(
            Q(startTime__lte=timezone.now() + timedelta(days=60)) &
            Q(endTime__gte=timezone.now() - timedelta(days=60))
        )
610045
def next_time(time, closing_time)
      loop do
        min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |best_time, rule|
          begin
            new_time = rule.next_time(time, start_time, best_time || closing_time)
            [best_time, new_time].compact.min
          rescue StopIteration
            best_time
          end
        end
        break unless min_time
        next (time = min_time + 1) if exception_time?(min_time)
        break Occurrence.new(min_time, min_time + duration)
      end
    end
1116507
def next(self):
        
        # Get next particle details
        x, y = self._move(self)
        colour = self._next_colour(self)
        char = self._next_char(self)
        self._last = char, x, y, colour[0], colour[1], colour[2]
        self.time += 1

        # Trigger any configured events
        if self.time == 1 and self._on_create is not None:
            self._on_create(self)
        elif self.life_time == self.time and self._on_destroy is not None:
            self._on_destroy(self)
        elif self._on_each is not None:
            self._on_each(self)

        return self._last
609068
def enumerate_occurrences(opening_time, closing_time = nil, options = {})
      opening_time = TimeUtil.match_zone(opening_time, start_time)
      closing_time = TimeUtil.match_zone(closing_time, start_time)
      opening_time += TimeUtil.subsec(start_time) - TimeUtil.subsec(opening_time)
      opening_time = start_time if opening_time < start_time
      spans = options[:spans] == true && duration != 0
      Enumerator.new do |yielder|
        reset
        t1 = full_required? ? start_time : opening_time
        t1 -= duration if spans
        t1 = start_time if t1 < start_time
        loop do
          break unless (t0 = next_time(t1, closing_time))
          break if closing_time && t0 > closing_time
          if (spans ? (t0.end_time > opening_time) : (t0 >= opening_time))
            yielder << (block_given? ? yield(t0) : t0)
          end
          t1 = t0 + 1
        end
      end
    end
615901
def _upcoming_datetime_from(self):
        
        nextDt = self.__localAfter(timezone.localtime(), dt.time.max,
                                   excludeCancellations=True,
                                   excludeExtraInfo=True)
        return nextDt
1266254
def this_and_prev(iterable):
    """"""
    try:
        item = next(iterable)
        while True:
            next_item = next(iterable)
            yield item, next_item
            item = next_item
    except StopIteration:
        return
39842
def started_after(self, date):
        '''
        
        '''
        dt = Timestamp(date)
        starts = self.groupby(self._oid).apply(lambda df: df._start.min())
        oids = set(starts[starts > dt].index.tolist())
        return self[self._oid.apply(lambda v: v in oids)]