diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ac818488328e5cc240a16c89c5f55c388e4b8b61..dc1f385d38af6dc4dca53c5a90c0816f619924b5 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -24,6 +24,8 @@ Fixed
 ~~~~~
 
 * Optimize exam model and add reference to exams at extra lessons.
+* Lessons weren't shown as cancelled on teacher or room timetables
+  if events had replaced them.
 
 `2.3`_ - 2022-03-21
 -------------------
diff --git a/aleksis/apps/chronos/templates/chronos/partials/lesson.html b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
index 523b3c62a6885f8dbc06def6daeda62246cb241e..3fa1f75788ae6433bc1bf2ef9983a06df8fb59ff 100644
--- a/aleksis/apps/chronos/templates/chronos/partials/lesson.html
+++ b/aleksis/apps/chronos/templates/chronos/partials/lesson.html
@@ -5,7 +5,7 @@
         {# Display background color only if lesson is not cancelled and it is not the old room #}
         {% if not smart %}
           {% include "chronos/partials/subject_colour.html" with subject=lesson_period.lesson.subject %}
-        {% elif not sub.cancelled and not lesson_period.get_substitution.cancelled_for_teachers %}
+        {% elif not sub.cancelled and not lesson_period.get_substitution.cancelled_for_teachers and not lesson_period.replaced_by_event %}
           {% if not type.value == "room" or lesson_period.room == lesson_period.get_room or lesson_period.get_room == el %}
             {% if sub and sub.subject %}
               {% include "chronos/partials/subject_colour.html" with subject=sub.subject %}
@@ -17,10 +17,15 @@
         {% endwith %}
         "
         {# Add CSS class for sub when it's a sub #}
-     class="{% if lesson_period.get_substitution and smart %}lesson-with-sub{% endif %}"
+     class="{% if smart %}{% if lesson_period.get_substitution or lesson_period.replaced_by_event %}lesson-with-sub{% endif %}{% endif %}"
 >
   <p>
-    {% if lesson_period.get_substitution and smart %}
+    {% if lesson_period.replaced_by_event and smart %}
+      {% include "chronos/partials/groups.html" with groups=lesson_period.lesson.groups.all %}
+      {% include "chronos/partials/subject.html" with subject=lesson_period.lesson.subject %}
+      <br/>
+      <span class="badge new green">{% trans "Cancelled due to an event" %}</span>
+    {% elif lesson_period.get_substitution and smart %}
       {% with sub=lesson_period.get_substitution %}
         {# SUBSTITUTION #}
         {% if type.value == "room" and lesson_period.room != lesson_period.get_room and lesson_period.get_room != el %}
diff --git a/aleksis/apps/chronos/util/build.py b/aleksis/apps/chronos/util/build.py
index ddfa790c7c674903dcbfb6edea063d504e779572..60e94895d5abf0eae5c1943eabcccb7bf91c2ab3 100644
--- a/aleksis/apps/chronos/util/build.py
+++ b/aleksis/apps/chronos/util/build.py
@@ -119,11 +119,6 @@ def build_timetable(
     else:
         events = events.on_day(date_ref)
 
-    if is_person:
-        events = events.filter_from_person(obj)
-    else:
-        events = events.filter_from_type(type_, obj)
-
     events = events.only(
         "id",
         "title",
@@ -136,8 +131,15 @@ def build_timetable(
         "period_to__weekday",
         "period_to__period",
     )
+
+    if is_person:
+        events_to_display = events.filter_from_person(obj)
+    else:
+        events_to_display = events.filter_from_type(type_, obj)
+
     # Sort events in a dict
     events_per_period = {}
+    events_for_replacement_per_period = {}
     for event in events:
         if is_week and event.date_start < date_ref[TimePeriod.weekday_min]:
             # If start date not in current week, set weekday and period to min
@@ -175,16 +177,30 @@ def build_timetable(
                 period_to = TimePeriod.period_max
 
             for period in range(period_from, period_to + 1):
-                if period not in events_per_period:
-                    events_per_period[period] = {} if is_week else []
+                # The following events are possibly replacing some lesson periods
+                if period not in events_for_replacement_per_period:
+                    events_for_replacement_per_period[period] = {} if is_week else []
 
-                if is_week and weekday not in events_per_period[period]:
-                    events_per_period[period][weekday] = []
+                if is_week and weekday not in events_for_replacement_per_period[period]:
+                    events_for_replacement_per_period[period][weekday] = []
 
                 if not is_week:
-                    events_per_period[period].append(event)
+                    events_for_replacement_per_period[period].append(event)
                 else:
-                    events_per_period[period][weekday].append(event)
+                    events_for_replacement_per_period[period][weekday].append(event)
+
+                # and the following will be displayed in the timetable
+                if event in events_to_display:
+                    if period not in events_per_period:
+                        events_per_period[period] = {} if is_week else []
+
+                    if is_week and weekday not in events_per_period[period]:
+                        events_per_period[period][weekday] = []
+
+                    if not is_week:
+                        events_per_period[period].append(event)
+                    else:
+                        events_per_period[period][weekday].append(event)
 
     if type_ == TimetableType.TEACHER:
         # Get matching supervisions
@@ -297,6 +313,11 @@ def build_timetable(
                         if period in events_per_period
                         else []
                     )
+                    events_for_replacement_for_this_period = (
+                        events_for_replacement_per_period[period].get(weekday, [])
+                        if period in events_for_replacement_per_period
+                        else []
+                    )
                     lesson_periods_for_this_period = (
                         lesson_periods_per_period[period].get(weekday, [])
                         if period in lesson_periods_per_period
@@ -305,19 +326,21 @@ def build_timetable(
 
                     # Add lesson periods
                     if lesson_periods_for_this_period:
-                        if events_for_this_period:
+                        if events_for_replacement_for_this_period:
                             # If there is a event in this period,
                             # we have to check whether the actual lesson is taking place.
 
-                            lesson_periods_to_keep = []
                             for lesson_period in lesson_periods_for_this_period:
-                                if not lesson_period.is_replaced_by_event(
-                                    events_for_this_period,
+                                replaced_by_event = lesson_period.is_replaced_by_event(
+                                    events_for_replacement_for_this_period,
                                     [obj] if type_ == TimetableType.GROUP else None,
+                                )
+                                lesson_period.replaced_by_event = replaced_by_event
+                                if not replaced_by_event or (
+                                    replaced_by_event and not type_ == TimetableType.GROUP
                                 ):
-                                    lesson_periods_to_keep.append(lesson_period)
+                                    col.append(lesson_period)
 
-                            col += lesson_periods_to_keep
                         else:
                             col += lesson_periods_for_this_period