diff --git a/aleksis/apps/chronos/model_extensions.py b/aleksis/apps/chronos/model_extensions.py
index 096b43e22c2c8094d547bbec57f70619cecb99e6..ce6c1810fd461edf10b6a18238c5d38712ce33a4 100644
--- a/aleksis/apps/chronos/model_extensions.py
+++ b/aleksis/apps/chronos/model_extensions.py
@@ -169,19 +169,4 @@ def send_notifications(sender: Revision, **kwargs):
         if change.deleted:
             continue
 
-        dt_start, dt_end = change.instance.time_range
-        dt_start = dt_start.replace(tzinfo=zoneinfo.ZoneInfo(settings.TIME_ZONE))
-        dt_end = dt_end.replace(tzinfo=zoneinfo.ZoneInfo(settings.TIME_ZONE))
-
-        send_time = get_site_preferences()["chronos__time_for_sending_notifications"]
-
-        start_range = timezone.now().replace(hour=send_time.hour, minute=send_time.minute)
-        if timezone.now().time() > send_time:
-            start_range = start_range - timedelta(days=1)
-        end_range = start_range + timedelta(days=1)
-
-        if dt_start <= end_range and dt_end >= start_range:
-            # Skip this because it's not in the current range for notifications
-            continue
-
         send_notifications_for_object(change.instance)
diff --git a/aleksis/apps/chronos/preferences.py b/aleksis/apps/chronos/preferences.py
index 6391b696b3852d7b281a94366e04b5a3bc3fd27e..7b3857c0b5f11c04e0753f50ac1576df0859c783 100644
--- a/aleksis/apps/chronos/preferences.py
+++ b/aleksis/apps/chronos/preferences.py
@@ -71,13 +71,23 @@ class AffectedGroupsUseParentGroups(BooleanPreference):
     )
 
 
+@site_preferences_registry.register
+class DaysInAdvanceNotifications(IntegerPreference):
+    section = chronos
+    name = "days_in_advance_notifications"
+    default = 1
+    verbose_name = _("How many days in advance users should be notified about timetable changes?")
+
 @site_preferences_registry.register
 class TimeForSendingNotifications(TimePreference):
     section = chronos
     name = "time_for_sending_notifications"
     default = time(17, 00)
-    verbose_name = _("Time for sending notifications for the next day")
+    verbose_name = _("Time for sending notifications about timetable changes")
     required = True
+    help_text = _("This is only used for scheduling notifications "
+                  "which doesn't affect the time period configured above. "
+                  "All other notifications affecting the next days are sent immediately.")
 
 
 @site_preferences_registry.register
diff --git a/aleksis/apps/chronos/tasks.py b/aleksis/apps/chronos/tasks.py
deleted file mode 100644
index 90f3ed3eacdaccab2ebd7008d8976e4d49b7798b..0000000000000000000000000000000000000000
--- a/aleksis/apps/chronos/tasks.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from django.utils import timezone
-
-from aleksis.apps.chronos.models import (
-    Event,
-    ExtraLesson,
-    LessonSubstitution,
-    SupervisionSubstitution,
-)
-from aleksis.apps.chronos.util.notifications import send_notifications_for_object
-from aleksis.core.celery import app
-
-
-@app.task(name="chronos_send_notifications_for_next_day")
-def send_notifications_for_next_day():
-    """Send notifications for next day."""
-    next_day = timezone.now().date() + timezone.timedelta(days=1)
-
-    relevant_objects = []
-    relevant_objects += LessonSubstitution.objects.on_day(next_day)
-    relevant_objects += ExtraLesson.objects.on_day(next_day)
-    relevant_objects += Event.objects.on_day(next_day)
-    relevant_objects += SupervisionSubstitution.objects.filter(date=next_day)
-
-    for instance in relevant_objects:
-        send_notifications_for_object(instance)
diff --git a/aleksis/apps/chronos/util/notifications.py b/aleksis/apps/chronos/util/notifications.py
index 9cfaea28f2b779e61082fd04fd0a377a264dab92..25216a2e442094e061773800dff98c77f1ab7168 100644
--- a/aleksis/apps/chronos/util/notifications.py
+++ b/aleksis/apps/chronos/util/notifications.py
@@ -1,3 +1,4 @@
+import zoneinfo
 from typing import Union
 from urllib.parse import urljoin
 
@@ -6,8 +7,10 @@ from django.urls import reverse
 from django.utils.formats import date_format
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import ngettext
-
+from django.utils import timezone
+from datetime import timedelta, datetime
 from aleksis.core.models import Notification, Person
+from aleksis.core.util.core_helpers import get_site_preferences
 
 from ..models import Event, ExtraLesson, LessonSubstitution, SupervisionSubstitution
 
@@ -170,6 +173,30 @@ def send_notifications_for_object(
         ),
     )
 
+    dt_start, dt_end = instance.time_range
+    dt_start = dt_start.replace(tzinfo=zoneinfo.ZoneInfo(settings.TIME_ZONE))
+    dt_end = dt_end.replace(tzinfo=zoneinfo.ZoneInfo(settings.TIME_ZONE))
+
+    send_time = get_site_preferences()["chronos__time_for_sending_notifications"]
+    number_of_days = get_site_preferences()["chronos__days_in_advance_notifications"]
+
+    start_range = timezone.now().replace(hour=send_time.hour, minute=send_time.minute)
+    if timezone.now().time() > send_time:
+        start_range = start_range - timedelta(days=1)
+    end_range = start_range + timedelta(days=number_of_days)
+
+    if dt_start < start_range and dt_end < end_range:
+        # Skip this, because the change is in the past
+        return
+
+    if dt_start <= end_range and dt_end >= start_range:
+        # Send immediately
+        send_at = timezone.now()
+    else:
+        # Schedule for later
+        send_at = datetime.combine(dt_start.date() - timedelta(days=number_of_days), send_time).replace(tzinfo=zoneinfo.ZoneInfo(settings.TIME_ZONE))
+
+
     for recipient in recipients:
         if recipient.preferences["chronos__send_notifications"]:
             n = Notification(
@@ -178,5 +205,6 @@ def send_notifications_for_object(
                 title=_("There are current changes to your timetable."),
                 description=description,
                 link=url,
+                send_at=send_at
             )
             n.save()