Beispiel #1
0
def recurrence_int_sequence(sequence):
    """ Generates a sequence of integer representations from a sequence of
    dateime instances.

    """
    for dt in sequence:
        yield dt2int(dt)
Beispiel #2
0
 def test_dt2int_less_MAX32(self, utc):
     from plone.event.utils import dt2int
     dt = mock.Mock()
     dd = mock.Mock()
     utc.return_value = dd
     dd.year = 2011
     dd.month = 11
     dd.day = 24
     dd.hour = 14
     dd.minute = 16
     self.assertRaises(OverflowError, lambda: dt2int(dt))
Beispiel #3
0
def recurrence_int_sequence(sequence):
    """ Generates a sequence of integer representations from a sequence of
    dateime instances.

    :param sequence: An iterable sequence of datetime instances.
    :type sequence: iterable
    :returns: Generator of integer representations of datetime instances.
    :rtype: generator

    """
    for dt in sequence:
        yield dt2int(dt)
Beispiel #4
0
 def test_dt2int_more_MAX32(self, utc):
     from plone.event.utils import dt2int
     dt = mock.Mock()
     dd = mock.Mock()
     utc.return_value = dd
     dd.year = 2011
     dd.month = 11
     dd.day = 24
     dd.hour = 14
     dd.minute = 16
     value = 1077778936
     self.assertEqual(dt2int(dt), value)
Beispiel #5
0
def filter_and_resort(context, brains, start, end, sort, sort_reverse):
    """#114 sorting bug is fallout from a Products.DateRecurringIndex
    limitation. The index contains a set of start and end dates
    represented as integer: that allows valid slicing of searches.
    However the returned brains have a .start attribute which is
    the start DateTime of the *first* occurrence of an event.

    This results in mis-sorting of search results if the next occurrence
    of event B is after the next occurrence of event A, but the first
    occurrence of event B is *before* the first occurrence of event A.
    The catalog results sort that as B<A instead of A<B.

    This method works around that issue by extracting all occurrence
    start/end from the index, and then sorting on the actual next start/end.

    For ongoing events which have an occurrence starting in the past
    but ending in the future, the past start of that ongoing occurrence
    is selected, so this will show up right at the start of the result.

    :param context: [required] A context object.
    :type context: Content object

    :param brains: [required] catalog brains
    :type brains: catalog brains

    :param start: [required] min end datetime (sic!)
    :type start: Python datetime.

    :param end: [required] max start datetime (sic!)
    :type start: Python datetime.

    :param sort_reverse: Change the order of the sorting.
    :type sort_reverse: boolean

    :param sort: Which field to sort on
    :type sort: 'start' or 'end'

    :returns: catalog brains
    :rtype: catalog brains

    """
    _start = dt2int(start)  # index contains longint sets
    _end = dt2int(end)
    catalog = getToolByName(context, 'portal_catalog')
    items = []  # (start:int, occurrence:brain) pairs
    for brain in brains:
        # brain.start metadata reflects first occurrence.
        # instead, get all occurrence start/end from raw index
        idx = catalog.getIndexDataForRID(brain.getRID())
        _allstarts = sorted(idx['start'])
        _allends = sorted(idx['end'])
        # assuming (start, end) pairs belong together
        # assert(len(_allstarts) == len(_allends))
        _occ = six.moves.zip(_allstarts, _allends)
        if start:
            _occ = [(s, e) for (s, e) in _occ if e >= _start]
        if end:
            _occ = [(s, e) for (s, e) in _occ if s <= _end]
        if not _occ:
            continue
        if sort == 'start':
            # first start can be before filter window if end is in window
            _first = min([s for (s, e) in _occ])
        elif sort == 'end':
            _first = min([e for (s, e) in _occ])
        items.append((_first, brain))  # key on next start/end

    # sort brains by next start, discard sort key
    data = [x[1] for x in sorted(items, key=lambda x: x[0])]
    if sort_reverse:
        data.reverse()
    return data
Beispiel #6
0
def filter_and_resort(context, brains, start, end, sort, sort_reverse):
    """#114 sorting bug is fallout from a Products.DateRecurringIndex
    limitation. The index contains a set of start and end dates
    represented as integer: that allows valid slicing of searches.
    However the returned brains have a .start attribute which is
    the start DateTime of the *first* occurrence of an event.

    This results in mis-sorting of search results if the next occurrence
    of event B is after the next occurrence of event A, but the first
    occurrence of event B is *before* the first occurrence of event A.
    The catalog results sort that as B<A instead of A<B.

    This method works around that issue by extracting all occurrence
    start/end from the index, and then sorting on the actual next start/end.

    For ongoing events which have an occurrence starting in the past
    but ending in the future, the past start of that ongoing occurrence
    is selected, so this will show up right at the start of the result.

    :param context: [required] A context object.
    :type context: Content object

    :param brains: [required] catalog brains
    :type brains: catalog brains

    :param start: [required] min end datetime (sic!)
    :type start: Python datetime.

    :param end: [required] max start datetime (sic!)
    :type start: Python datetime.

    :param sort_reverse: Change the order of the sorting.
    :type sort_reverse: boolean

    :param sort: Which field to sort on
    :type sort: 'start' or 'end'

    :returns: catalog brains
    :rtype: catalog brains

    """
    _start = dt2int(start)  # index contains longint sets
    _end = dt2int(end)
    catalog = getToolByName(context, 'portal_catalog')
    items = []  # (start:int, occurrence:brain) pairs
    for brain in brains:
        # brain.start metadata reflects first occurrence.
        # instead, get all occurrence start/end from raw index
        idx = catalog.getIndexDataForRID(brain.getRID())
        _allstarts = sorted(idx['start'])
        _allends = sorted(idx['end'])
        # assuming (start, end) pairs belong together
        #assert(len(_allstarts) == len(_allends))
        _occ = itertools.izip(_allstarts, _allends)
        if start:
            _occ = [(s, e) for (s, e) in _occ if e >= _start]
        if end:
            _occ = [(s, e) for (s, e) in _occ if s <= _end]
        if not _occ:
            continue
        if sort == 'start':
            # first start can be before filter window if end is in window
            _first = min([s for (s, e) in _occ])
        elif sort == 'end':
            _first = min([e for (s, e) in _occ])
        items.append((_first, brain))  # key on next start/end

    # sort brains by next start, discard sort key
    data = [x[1] for x in sorted(items, key=lambda x: x[0])]
    if sort_reverse:
        data.reverse()
    return data
 def _convert(self, value, default=None):
     """Convert record keys/datetimes into int representation.
     """
     return dt2int(value) or default
Beispiel #8
0
 def test_dt2int_dt_is_None(self):
     from plone.event.utils import dt2int
     self.assertFalse(dt2int(None))
 def _convert(self, value, default=None):
     """Convert record keys/datetimes into int representation.
     """
     return dt2int(value) or default