def get_nearest_prev_point(self, point): """Return the largest point < some arbitrary point.""" if self.is_on_sequence(point): return self.get_prev_point(point) p_iso_point = point_parse(point.value) p_iso_excl = None if self.exclusion: p_iso_excl = point_parse(self.exclusion.value) prev_iso_point = None for recurrence_iso_point in self.recurrence: if (recurrence_iso_point > p_iso_point or (p_iso_excl and recurrence_iso_point == p_iso_excl)): # Technically, >=, but we already test for this above. break prev_iso_point = recurrence_iso_point if prev_iso_point is None: return None nearest_point = ISO8601Point(str(prev_iso_point)) if nearest_point == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, nearest_point, point) if self.exclusion and nearest_point == self.exclusion: return self.get_prev_point(nearest_point) return nearest_point
def get_nearest_prev_point(self, point): """Return the largest point < some arbitrary point.""" if self.is_on_sequence(point): return self.get_prev_point(point) p_iso_point = point_parse(point.value) prev_cycle_point = None for recurrence_iso_point in self.recurrence: # Is recurrence point greater than arbitrary point? if recurrence_iso_point > p_iso_point: break recurrence_cycle_point = ISO8601Point(str(recurrence_iso_point)) if self.exclusions and recurrence_cycle_point in self.exclusions: break prev_cycle_point = recurrence_cycle_point if prev_cycle_point is None: return None if prev_cycle_point == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, prev_cycle_point, point) # Check all exclusions if self.exclusions and prev_cycle_point in self.exclusions: return self.get_prev_point(prev_cycle_point) return prev_cycle_point
def get_next_point_on_sequence(self, point): """Return the on-sequence point > point assuming that point is on-sequence, or None if out of bounds.""" result = None next_point = self.recurrence.get_next(point_parse(point.value)) if next_point: result = ISO8601Point(str(next_point)) if result == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, point, result) return result
def get_prev_point(self, point): """Return the previous point < point, or None if out of bounds.""" # may be None if out of the recurrence bounds res = None prev_point = self.recurrence.get_prev(point_parse(point.value)) if prev_point: res = ISO8601Point(str(prev_point)) if res == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, res, point) return res
def _check_and_cache_next_point(self, point, next_point): """Verify and cache the get_next_point return info.""" # Verify next_point != point. if next_point == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, next_point, point) # Cache the answer for point -> next_point. if (len(self._cached_next_point_values) > self._MAX_CACHED_POINTS): self._cached_next_point_values.popitem() self._cached_next_point_values[point.value] = next_point.value # Cache next_point as a valid starting point for this recurrence. if (len(self._cached_next_point_values) > self._MAX_CACHED_POINTS): self._cached_recent_valid_points.pop(0) self._cached_recent_valid_points.append(next_point)
def get_prev_point(self, point): """Return the previous point < point, or None if out of bounds.""" # may be None if out of the recurrence bounds res = None prev_point = self.recurrence.get_prev(point_parse(point.value)) if prev_point: res = ISO8601Point(str(prev_point)) if res == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, res, point) # Check if res point is in the list of exclusions # If so, check the previous point by recursion. # Once you have found a point that is *not* in the exclusion # list, you can return it. if self.exclusions and res in self.exclusions: return self.get_prev_point(res) return res
def get_next_point(self, point): """Return the next point > p, or None if out of bounds.""" try: return ISO8601Point(self._cached_next_point_values[point.value]) except KeyError: pass p_iso_point = point_parse(point.value) for recurrence_iso_point in self.recurrence: if recurrence_iso_point > p_iso_point: next_point_value = str(recurrence_iso_point) if (len(self._cached_next_point_values) > self._MAX_CACHED_POINTS): self._cached_next_point_values.popitem() self._cached_next_point_values[point.value] = next_point_value next_point = ISO8601Point(next_point_value) if next_point == point: raise SequenceDegenerateError(self.recurrence, SuiteSpecifics.DUMP_FORMAT, nearest_point, point) return next_point return None