diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TardinessNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TardinessNote.vue
index e5733941d9b7c47cafd0d96b9312a1814b76802b..a65c6bf5fe2e9425d31b5ba8bd68a8bd4497ebe1 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TardinessNote.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TardinessNote.vue
@@ -4,6 +4,7 @@ import {
   deletePersonalNotes,
   updatePersonalNotes,
 } from "./personal_notes.graphql";
+import { DateTime } from "luxon";
 import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
 import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
 import DeleteDialog from "aleksis.core/components/generic/dialogs/DeleteDialog.vue";
@@ -18,8 +19,11 @@ export default {
       return this.participation.noteWithTardiness;
     },
     lessonLength() {
-      // TODO: calculate lesson length in minutes
-      return 60;
+      const lessonStart = DateTime.fromISO(this.documentation.datetimeStart);
+      const lessonEnd = DateTime.fromISO(this.documentation.datetimeEnd);
+
+      let diff = lessonEnd.diff(lessonStart, 'minutes');
+      return diff.toObject().minutes;
     },
     model: {
       get() {
@@ -98,8 +102,7 @@ export default {
       };
     },
     lessonLengthRule(time) {
-      // FIXME: translation
-      return time <= lessonLength || this.$t("alsijil.personal_notes.lesson_length_exceeded");
+      return time == null || time <= this.lessonLength || this.$t("alsijil.personal_notes.lesson_length_exceeded");
     }
   },
   data() {