diff --git a/program/models.py b/program/models.py
index 0fafc80b6a3c7fedb587294bb61d5ffe31075338..e2f317fa1bfbcb508171126af0b6ef4d87249d74 100644
--- a/program/models.py
+++ b/program/models.py
@@ -18,10 +18,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-from datetime import datetime, timedelta
+from datetime import datetime
 
-from dateutil.relativedelta import relativedelta
-from dateutil.rrule import rrule
 from rest_framework.exceptions import ValidationError
 from versatileimagefield.fields import PPOIField, VersatileImageField
 
@@ -29,7 +27,6 @@ from django.contrib.auth.models import User
 from django.core.exceptions import ObjectDoesNotExist
 from django.db import models
 from django.db.models import Q, QuerySet
-from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
 from program.utils import parse_datetime
@@ -375,153 +372,6 @@ class Schedule(models.Model):
     class Meta:
         ordering = ("first_date", "start_time")
 
-    # FIXME: this does not belong here
-    @staticmethod
-    def generate_timeslots(schedule):
-        """
-        Returns a list of timeslot objects based on a schedule and its rrule
-        Returns past timeslots as well, starting from first_date (not today)
-        """
-        timeslots = []
-
-        # 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 == 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 == 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:
-                by_weekday_end = (1, 2, 3, 4, 5)
-        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 = by_weekday_end = (
-                int(schedule.by_weekday) if schedule.by_weekday is not None else None
-            )
-
-            # 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(
-                    freq=schedule.rrule.freq,
-                    dtstart=datetime.combine(schedule.first_date, schedule.start_time),
-                    interval=schedule.rrule.interval,
-                    until=schedule.last_date + relativedelta(days=+1),
-                    bysetpos=schedule.rrule.by_set_pos,
-                    byweekday=by_weekday_start,
-                )
-            )
-            ends = list(
-                rrule(
-                    freq=schedule.rrule.freq,
-                    dtstart=datetime.combine(last_date, schedule.end_time),
-                    interval=schedule.rrule.interval,
-                    until=schedule.last_date + relativedelta(days=+1),
-                    bysetpos=schedule.rrule.by_set_pos,
-                    byweekday=by_weekday_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
-            #       In this case we take the next day instead of rrule's calculated end
-            if starts[k] > ends[k]:
-                ends[k] = datetime.combine(starts[k] + relativedelta(days=+1), schedule.end_time)
-
-            """
-            Add a number of days to the generated dates?
-
-            This can be helpful for repetitions:
-
-            Examples:
-
-              1. If RRule is "Every 1st Monday" and we want its repetition always to be on the
-                 following day, the repetition's RRule is the same but add_days_no is 1
-
-                 If we would set the repetition to "Every 1st Tuesday" instead
-                 we will get unmeant results if the 1st Tuesday is before the 1st Monday
-                 (e.g. 1st Tue = May 1 2018, 1st Mon = May 7 2018)
-
-              2. If RRule is "Every 1st Friday" and we want its repetition always to be on the
-                 following business day, the repetition's RRule is the same but add_days_no is 1
-                 and add_business_days_only is True (e.g. original date = Fri, March 2 2018;
-                 generated date = Mon, March 5 2018)
-
-            In the UI these can be presets:
-                "On the following day" (add_days_no=1,add_business_days_only=False) or
-                "On the following business day" (add_days_no=1,add_business_days_only=True)
-
-            """
-            if schedule.add_days_no is not None and schedule.add_days_no > 0:
-                # If only business days and weekday is Fri, Sat or Sun: add add_days_no beginning
-                # from Sunday
-                weekday = datetime.date(starts[k]).weekday()
-                if schedule.add_business_days_only and weekday > 3:
-                    days_until_sunday = 6 - weekday
-                    starts[k] = starts[k] + relativedelta(
-                        days=+days_until_sunday + schedule.add_days_no
-                    )
-                    ends[k] = ends[k] + relativedelta(
-                        days=+days_until_sunday + schedule.add_days_no
-                    )
-                else:
-                    starts[k] = starts[k] + relativedelta(days=+schedule.add_days_no)
-                    ends[k] = ends[k] + relativedelta(days=+schedule.add_days_no)
-
-                if ends[k].date() > schedule.last_date:
-                    schedule.last_date = ends[k].date()
-            timeslots.append(
-                TimeSlot(
-                    schedule=schedule,
-                    start=timezone.make_aware(starts[k], is_dst=True),
-                    end=timezone.make_aware(ends[k], is_dst=True),
-                )
-            )
-
-        return timeslots
-
     # FIXME: this does not belong here
     @staticmethod
     def generate_conflicts(timeslots):
diff --git a/program/services.py b/program/services.py
index a6d509dffe0d6216759c5febf7552d042d0cf207..09dc72956755b057056006c2dc3a232b8da86e0b 100644
--- a/program/services.py
+++ b/program/services.py
@@ -19,6 +19,8 @@
 
 from datetime import datetime, time, timedelta
 
+from dateutil.relativedelta import relativedelta
+from dateutil.rrule import rrule
 from rest_framework.exceptions import ValidationError
 
 from django.core.exceptions import ObjectDoesNotExist
@@ -391,10 +393,155 @@ def make_conflicts(sdl, schedule_pk, show_pk):
             )
             gen_schedule.first_date = last_timeslot.start.date() + timedelta(days=1)
 
-    timeslots = Schedule.generate_timeslots(gen_schedule)
+    timeslots = generate_timeslots(gen_schedule)
 
     # Generate conflicts and add schedule
     conflicts = Schedule.generate_conflicts(timeslots)
     conflicts["schedule"] = model_to_dict(schedule)
 
     return conflicts
+
+
+# TODO: add type annotations
+def generate_timeslots(schedule):
+    """
+    Returns a list of timeslot objects based on a schedule and its rrule
+    Returns past timeslots as well, starting from first_date (not today)
+    """
+    timeslots = []
+
+    # 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 == 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 == 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:
+            by_weekday_end = (1, 2, 3, 4, 5)
+    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 = by_weekday_end = (
+            int(schedule.by_weekday) if schedule.by_weekday is not None else None
+        )
+
+        # 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(
+                freq=schedule.rrule.freq,
+                dtstart=datetime.combine(schedule.first_date, schedule.start_time),
+                interval=schedule.rrule.interval,
+                until=schedule.last_date + relativedelta(days=+1),
+                bysetpos=schedule.rrule.by_set_pos,
+                byweekday=by_weekday_start,
+            )
+        )
+        ends = list(
+            rrule(
+                freq=schedule.rrule.freq,
+                dtstart=datetime.combine(last_date, schedule.end_time),
+                interval=schedule.rrule.interval,
+                until=schedule.last_date + relativedelta(days=+1),
+                bysetpos=schedule.rrule.by_set_pos,
+                byweekday=by_weekday_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
+        #       In this case we take the next day instead of rrule's calculated end
+        if starts[k] > ends[k]:
+            ends[k] = datetime.combine(starts[k] + relativedelta(days=+1), schedule.end_time)
+
+        """
+        Add a number of days to the generated dates?
+
+        This can be helpful for repetitions:
+
+        Examples:
+
+          1. If RRule is "Every 1st Monday" and we want its repetition always to be on the
+             following day, the repetition's RRule is the same but add_days_no is 1
+
+             If we would set the repetition to "Every 1st Tuesday" instead
+             we will get unmeant results if the 1st Tuesday is before the 1st Monday
+             (e.g. 1st Tue = May 1 2018, 1st Mon = May 7 2018)
+
+          2. If RRule is "Every 1st Friday" and we want its repetition always to be on the
+             following business day, the repetition's RRule is the same but add_days_no is 1
+             and add_business_days_only is True (e.g. original date = Fri, March 2 2018;
+             generated date = Mon, March 5 2018)
+
+        In the UI these can be presets:
+            "On the following day" (add_days_no=1,add_business_days_only=False) or
+            "On the following business day" (add_days_no=1,add_business_days_only=True)
+
+        """
+        if schedule.add_days_no is not None and schedule.add_days_no > 0:
+            # If only business days and weekday is Fri, Sat or Sun: add add_days_no beginning
+            # from Sunday
+            weekday = datetime.date(starts[k]).weekday()
+            if schedule.add_business_days_only and weekday > 3:
+                days_until_sunday = 6 - weekday
+                starts[k] = starts[k] + relativedelta(
+                    days=+days_until_sunday + schedule.add_days_no
+                )
+                ends[k] = ends[k] + relativedelta(days=+days_until_sunday + schedule.add_days_no)
+            else:
+                starts[k] = starts[k] + relativedelta(days=+schedule.add_days_no)
+                ends[k] = ends[k] + relativedelta(days=+schedule.add_days_no)
+
+            if ends[k].date() > schedule.last_date:
+                schedule.last_date = ends[k].date()
+        timeslots.append(
+            TimeSlot(
+                schedule=schedule,
+                start=timezone.make_aware(starts[k], is_dst=True),
+                end=timezone.make_aware(ends[k], is_dst=True),
+            )
+        )
+
+    return timeslots