# HG changeset patch # User Paul Boddie # Date 1508533875 -7200 # Node ID ecdbe127443aaadb257aeb8cf16a2ba4b3d16603 # Parent c79242324f107488af09a43787626bf56ad8741a# Parent 102a5f873a8b3c53faf2796770ec886c5b4ee730 Merged changes from the default branch. diff -r c79242324f10 -r ecdbe127443a imiptools/data.py --- a/imiptools/data.py Fri Oct 20 22:40:55 2017 +0200 +++ b/imiptools/data.py Fri Oct 20 23:11:15 2017 +0200 @@ -1214,11 +1214,11 @@ return delegators -def make_rule_period(start, duration, tzid, attr): +def make_rule_period(start, duration, attr, tzid): """ Make a period for the rule period starting at 'start' with the given - 'duration' employing the given 'tzid' and datetime 'attr'. + 'duration' employing the given datetime 'attr' and 'tzid'. """ # Determine the resolution of the period. @@ -1232,6 +1232,44 @@ return RecurringPeriod(start, end, tzid, "RRULE", attr) +def get_rule_periods(rrule, start, duration, attr, tzid, end, inclusive=False): + + """ + Return periods for the given 'rrule', employing the 'start', 'duration', + datetime 'attr' and 'tzid'. + + The specified 'end' datetime indicates the end of the window for which + periods shall be computed. + + If 'inclusive' is set to a true value, any period occurring at the 'end' + will be included. + """ + + parameters = rrule and get_parameters(rrule) + selector = get_rule(start, rrule) + + until = parameters.get("UNTIL") + + if until: + until_dt = to_timezone(get_datetime(until, attr), tzid) + end = end and min(until_dt, end) or until_dt + inclusive = True + + # Obtain period instances, starting from the main period. Since counting + # must start from the first period, filtering from a start date must be + # done after the instances have been obtained. + + periods = [] + + for recurrence_start in selector.materialise(start, end, + parameters.get("COUNT"), + parameters.get("BYSETPOS"), + inclusive): + + periods.append(make_rule_period(recurrence_start, duration, attr, tzid)) + + return periods + def get_periods(obj, start=None, end=None, inclusive=False): """ @@ -1261,35 +1299,21 @@ if not rrule: periods = [main_period] + # Recurrence rules create multiple instances to be checked. + # Conflicts may only be assessed within a period defined by policy + # for the agent, with instances outside that period being considered + # unchecked. + elif end or parameters and parameters.has_key("UNTIL") or parameters.has_key("COUNT"): - # Recurrence rules create multiple instances to be checked. - # Conflicts may only be assessed within a period defined by policy - # for the agent, with instances outside that period being considered - # unchecked. + # Define a selection period with a start point. The end will be handled + # in the materialisation process. - selector = get_rule(dtstart, rrule) + selection_period = Period(start, None) periods = [] - until = parameters.get("UNTIL") - if until: - until_dt = to_timezone(get_datetime(until, dtstart_attr), tzid) - end = end and min(until_dt, end) or until_dt - inclusive = True - - # Define a selection period with a start point. The end will be handled - # in the materialisation process below. - - selection_period = Period(start, None) - - # Obtain period instances, starting from the main period. Since counting - # must start from the first period, filtering from a start date must be - # done after the instances have been obtained. - - for recurrence_start in selector.materialise(dtstart, end, - parameters.get("COUNT"), parameters.get("BYSETPOS"), inclusive): - - period = make_rule_period(recurrence_start, main_period.get_duration(), tzid, dtstart_attr) + for period in get_rule_periods(rrule, dtstart, + main_period.get_duration(), dtstart_attr, tzid, end, inclusive): # Use the main period where it occurs.