From 83fd04082b9510578c0ddcae5aea1026d2d29514 Mon Sep 17 00:00:00 2001 From: Ernesto Rico Schmidt <ernesto@helsinki.at> Date: Wed, 15 Feb 2023 17:16:47 -0400 Subject: [PATCH] Refactor generate_timeslots to not use ids/pks --- program/models.py | 96 +++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/program/models.py b/program/models.py index 8a0b3232..58d52d66 100644 --- a/program/models.py +++ b/program/models.py @@ -19,7 +19,6 @@ # from datetime import datetime, time, timedelta -from textwrap import dedent from dateutil.relativedelta import relativedelta from dateutil.rrule import rrule @@ -401,63 +400,64 @@ class Schedule(models.Model): Returns a list of timeslot objects based on a schedule and its rrule Returns past timeslots as well, starting from first_date (not today) """ - - by_week_no = None - by_week_no_end = None - by_weekday_end = int(schedule.by_weekday) - starts = [] - ends = [] timeslots = [] - # Handle ending weekday for timeslots over midnight - if schedule.end_time < schedule.start_time: - if schedule.by_weekday < 6: - by_weekday_end = int(schedule.by_weekday + 1) - else: - by_weekday_end = 0 - # Handle ending dates for timeslots over midnight + # adjust last_date if end_time is after midnight if schedule.end_time < schedule.start_time: last_date = schedule.first_date + timedelta(days=+1) else: last_date = schedule.first_date - if schedule.rrule.freq == 0: # Ignore weekdays for one-time timeslots - by_weekday_start = None - by_weekday_end = None - elif schedule.rrule.freq == 3 and schedule.rrule.pk == 2: # Daily timeslots - by_weekday_start = (0, 1, 2, 3, 4, 5, 6) - by_weekday_end = (0, 1, 2, 3, 4, 5, 6) + if schedule.rrule.freq == 3: # daily: Ignore schedule.by_weekday to set by_weekday + by_weekday_start = by_weekday_end = (0, 1, 2, 3, 4, 5, 6) + elif ( + schedule.rrule.freq == 2 + and schedule.rrule.interval == 1 + and schedule.rrule.by_weekdays is None + ): # weekly: Use schedule.by_weekday for by_weekday + by_weekday_start = by_weekday_end = int(schedule.by_weekday) + + # adjust by_weekday_end if end_time is after midnight + if schedule.end_time < schedule.start_time: + by_weekday_end = by_weekday_start + 1 if by_weekday_start < 6 else 0 elif ( - schedule.rrule.freq == 3 and schedule.rrule.pk == 3 - ): # Business days MO - FR/SA - by_weekday_start = (0, 1, 2, 3, 4) + schedule.rrule.freq == 2 + and schedule.rrule.interval == 1 + and schedule.rrule.by_weekdays == "0,1,2,3,4" + ): # weekly on business days: Use schedule.rrule.by_weekdays to set by_weekday + by_weekday_start = by_weekday_end = [ + int(wd) for wd in schedule.rrule.by_weekdays.split(",") + ] + + # adjust by_weekday_end if end_time is after midnight if schedule.end_time < schedule.start_time: - # End days for over midnight by_weekday_end = (1, 2, 3, 4, 5) - else: - by_weekday_end = (0, 1, 2, 3, 4) - elif schedule.rrule.freq == 2 and schedule.rrule.pk == 7: # Even calendar weeks - by_weekday_start = int(schedule.by_weekday) - by_week_no = list(range(2, 54, 2)) - # Reverse ending weeks if from Sun - Mon - if by_weekday_start == 6 and by_weekday_end == 0: - by_week_no_end = list(range(1, 54, 2)) - else: - by_week_no_end = by_week_no - elif schedule.rrule.freq == 2 and schedule.rrule.pk == 8: # Odd calendar weeks - by_weekday_start = int(schedule.by_weekday) - by_week_no = list(range(1, 54, 2)) - # Reverse ending weeks if from Sun - Mon - if by_weekday_start == 6 and by_weekday_end == 0: - by_week_no_end = list(range(2, 54, 2)) - else: - by_week_no_end = by_week_no + elif ( + schedule.rrule.freq == 2 + and schedule.rrule.interval == 1 + and schedule.rrule.by_weekdays == "5,6" + ): # weekly on weekends: Use schedule.rrule.by_weekdays to set by_weekday + by_weekday_start = by_weekday_end = [ + int(wd) for wd in schedule.rrule.by_weekdays.split(",") + ] + + # adjust by_weekday_end if end_time is after midnight + if schedule.end_time < schedule.start_time: + by_weekday_end = (6, 0) + elif schedule.rrule.freq == 0: # once: Ignore schedule.by_weekday to set by_weekday + by_weekday_start = by_weekday_end = None else: - by_weekday_start = int(schedule.by_weekday) + by_weekday_start = by_weekday_end = ( + int(schedule.by_weekday) if schedule.by_weekday else None + ) - if schedule.rrule.freq == 0: - starts.append(datetime.combine(schedule.first_date, schedule.start_time)) - ends.append(datetime.combine(last_date, schedule.end_time)) + # adjust by_weekday_end if end_time is after midnight + if schedule.end_time < schedule.start_time: + by_weekday_end = by_weekday_start + 1 if by_weekday_start < 6 else 0 + + if schedule.rrule.freq == 0: # once: + starts = [datetime.combine(schedule.first_date, schedule.start_time)] + ends = [datetime.combine(last_date, schedule.end_time)] else: starts = list( rrule( @@ -467,10 +467,8 @@ class Schedule(models.Model): until=schedule.last_date + relativedelta(days=+1), bysetpos=schedule.rrule.by_set_pos, byweekday=by_weekday_start, - byweekno=by_week_no, ) ) - ends = list( rrule( freq=schedule.rrule.freq, @@ -479,12 +477,10 @@ class Schedule(models.Model): until=schedule.last_date + relativedelta(days=+1), bysetpos=schedule.rrule.by_set_pos, byweekday=by_weekday_end, - byweekno=by_week_no_end, ) ) for k in range(min(len(starts), len(ends))): - # Correct dates for the (relatively seldom) case if: # E.g.: 1st Monday from 23:00:00 to 1st Tuesday 00:00:00 # produces wrong end dates if the 1st Tuesday is before the 1st Monday -- GitLab