diff --git a/Makefile b/Makefile
index d3c8cef122742051f08d5907b9a4696a241fa2f1..7dcbf364374dc7565702d6917ec52290ff6e93b7 100644
--- a/Makefile
+++ b/Makefile
@@ -46,6 +46,9 @@ loaddata.test:
 addpermissions:
 	$(POETRY_RUN_MANAGE) addpermissions
 
+addtimeslots:
+	$(POETRY_RUN_MANAGE) addtimeslots
+
 removestaleimages:
 	$(POETRY_RUN_MANAGE) removestaleimages
 
diff --git a/program/management/commands/addtimeslots.py b/program/management/commands/addtimeslots.py
new file mode 100644
index 0000000000000000000000000000000000000000..2950221203f23510667a47bde518f14c15cab7a9
--- /dev/null
+++ b/program/management/commands/addtimeslots.py
@@ -0,0 +1,70 @@
+from datetime import datetime
+
+from dateutil.rrule import rrule
+
+from django.core.management import BaseCommand
+from django.utils.timezone import make_aware
+from program.models import RRule, Schedule, TimeSlot
+
+
+class Command(BaseCommand):
+    help = "adds timeslots to the repeating schedules for one year"
+
+    def add_arguments(self, parser):
+        parser.add_argument(
+            "year",
+            help="The year ",
+            type=int,
+        )
+        parser.add_argument(
+            "--dry-run",
+            action="store_true",
+            help="Does not add the timeslots, just prints the number of timeslots to be added.",
+        )
+
+    def handle(self, *args, **options):
+        year = options["year"]
+        dry_run = options["dry_run"]
+
+        begin_of_year = datetime(year, 1, 1)
+        end_of_year = datetime(year, 12, 31)
+
+        once = RRule.objects.get(freq=0, count=1)
+
+        for schedule in (
+            Schedule.objects.exclude(rrule=once).filter(last_date=None).order_by("show__name")
+        ):
+            last_timeslot = schedule.timeslots.last()
+
+            # add timeslots to the schedules with no timeslot this year
+            # `begin_of_year` needs to be timezone aware for the comparison to work
+            if last_timeslot and last_timeslot.start < make_aware(begin_of_year):
+                freq = schedule.rrule.freq
+                interval = schedule.rrule.interval
+                dtstart = {"start": last_timeslot.start, "end": last_timeslot.end}
+                # `until` needs to be timezone aware because `dtstart` is
+                until = {"start": make_aware(end_of_year), "end": make_aware(end_of_year)}
+
+                # will need to skip the first recurrences, since they’re from the previous year
+                starts = rrule(
+                    freq=freq, interval=interval, dtstart=dtstart["start"], until=until["start"]
+                )
+                ends = rrule(
+                    freq=freq, interval=interval, dtstart=dtstart["end"], until=until["end"]
+                )
+
+                timeslots = [
+                    TimeSlot(schedule=schedule, start=start, end=end)
+                    for start, end in zip(starts[1:], ends[1:])
+                ]
+
+                if dry_run:
+                    self.stdout.write(
+                        self.style.WARNING(f"would add {len(timeslots)} timeslots to {schedule}")
+                    )
+                else:
+                    TimeSlot.objects.bulk_create(timeslots, ignore_conflicts=True)
+
+                    self.stdout.write(
+                        self.style.SUCCESS(f"added {len(timeslots)} timeslots to {schedule}")
+                    )