diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2bb4491ff40ed6d66ea3f7a903a02a59f26a2acf..ea33f0fa9c62bcc693684b1069aa8296eadc29da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ## [Unreleased]
 ### Added
 ### Changed
+- Waiting time and processing time now uses consistent calculations. [@hpage](https://gitlab.ewi.tudelft.nl/hpage)
 ### Fixed
  - Fix the copying of labs  [@mmadara](https://gitlab.ewi.tudelft.nl/mmadara)
 
diff --git a/src/main/java/nl/tudelft/queue/controller/EditionStatusController.java b/src/main/java/nl/tudelft/queue/controller/EditionStatusController.java
index c28e7b29cc6064bd3f2f234deb4563caee8fe95e..c05cbf99a486c098d41b6a65e96779ccb7127b3c 100644
--- a/src/main/java/nl/tudelft/queue/controller/EditionStatusController.java
+++ b/src/main/java/nl/tudelft/queue/controller/EditionStatusController.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.queue.controller;
 
+import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeSet;
@@ -41,6 +42,7 @@ import nl.tudelft.queue.model.enums.RequestType;
 import nl.tudelft.queue.model.labs.Lab;
 import nl.tudelft.queue.model.records.RequestCountRecord;
 import nl.tudelft.queue.service.EditionStatusService;
+import nl.tudelft.queue.service.SessionService;
 
 @Validated
 @RestController
@@ -52,6 +54,9 @@ public class EditionStatusController {
 	@Autowired
 	private AssignmentCacheManager aCache;
 
+	@Autowired
+	private SessionService sessionService;
+
 	/**
 	 * Creates and returns the data for a histogram regarding the status of requests over time. The data for
 	 * requests can be filtered on labs, assignments and rooms to only selectively count.
@@ -135,6 +140,7 @@ public class EditionStatusController {
 			@RequestParam(required = false, defaultValue = "") List<RequestType> type) {
 		List<LabRequest> requests = ess.getFilteredRequests(labs, assignments, rooms, type);
 
+		// we use ESS here even though it's not really edition statistics.
 		return new LabStatisticsViewDto(
 				ess.countDistinctUsers(requests),
 				ess.countDistinctAssistants(requests),
@@ -148,8 +154,8 @@ public class EditionStatusController {
 						.map(AssignmentCountStatisticsViewDto::getAssignmentName)
 						.orElse("N/A"), // order preserving in case of tie
 				ess.mostCountedName(ess.countRequestsPerRoom(rooms, requests)),
-				ess.averageWaitingTime(requests),
-				ess.averageProcessingTime(requests));
+				ess.averageWaitingTime(requests, ChronoUnit.MILLIS),
+				ess.averageProcessingTime(requests, ChronoUnit.MILLIS));
 	}
 
 	/**
@@ -185,7 +191,7 @@ public class EditionStatusController {
 	 * @param  assignments The assignments to filter on.
 	 * @param  rooms       The rooms to filter on.
 	 * @param  type        The request types to filter on.
-	 * @return             The names of assignments mapped to the number of times that room occurs.
+	 * @return             The names of assignments mapped to the number of times that room occurs.;
 	 */
 	@GetMapping("/edition/{editionId}/status/freq/room")
 	@PreAuthorize("@permissionService.canViewEditionStatus(#editionId)")
diff --git a/src/main/java/nl/tudelft/queue/controller/SessionStatusController.java b/src/main/java/nl/tudelft/queue/controller/SessionStatusController.java
index 771e8b162abd2926e47d0b575b616996533c4dee..3b089229855236dc8a396302bb8b6e05c15aea70 100644
--- a/src/main/java/nl/tudelft/queue/controller/SessionStatusController.java
+++ b/src/main/java/nl/tudelft/queue/controller/SessionStatusController.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.queue.controller;
 
+import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -82,8 +83,8 @@ public class SessionStatusController {
 						requests.stream().filter(rq -> rq.getRequestType() == RequestType.SUBMISSION)
 								.count()),
 				(long) qSession.getQueue().size(),
-				editionStatusService.averageWaitingTime(requests),
-				editionStatusService.averageProcessingTime(requests));
+				editionStatusService.averageWaitingTime(requests, ChronoUnit.MILLIS),
+				editionStatusService.averageProcessingTime(requests, ChronoUnit.MILLIS));
 	}
 
 	/**
diff --git a/src/main/java/nl/tudelft/queue/dto/view/statistics/BucketStatisticsViewDto.java b/src/main/java/nl/tudelft/queue/dto/view/statistics/BucketStatisticsViewDto.java
index 089c3f398a3fbd01df9c292dbbfec835cfd1d26c..3bc017889cb15418006b90d7aebe05418235ea4a 100644
--- a/src/main/java/nl/tudelft/queue/dto/view/statistics/BucketStatisticsViewDto.java
+++ b/src/main/java/nl/tudelft/queue/dto/view/statistics/BucketStatisticsViewDto.java
@@ -32,7 +32,7 @@ import lombok.NoArgsConstructor;
 public class BucketStatisticsViewDto {
 
 	// corresponds to edition, but entries are course names so it makes it more presentable
-	private Map<String, Long> bucketData;
+	private Map<String, ? extends Number> bucketData;
 
 	// what gets displayed on the chart under this bucket.
 	private String bucketLabel;
diff --git a/src/main/java/nl/tudelft/queue/dto/view/statistics/LabStatisticsViewDto.java b/src/main/java/nl/tudelft/queue/dto/view/statistics/LabStatisticsViewDto.java
index 89d6201ea608a6f6606781ff2cf9426a75f3101a..8c2fac3e172c88dafe912aff4298a57503889c83 100644
--- a/src/main/java/nl/tudelft/queue/dto/view/statistics/LabStatisticsViewDto.java
+++ b/src/main/java/nl/tudelft/queue/dto/view/statistics/LabStatisticsViewDto.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.queue.dto.view.statistics;
 
+import java.util.OptionalDouble;
+
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -39,6 +41,6 @@ public class LabStatisticsViewDto {
 	private String assignment;
 	private String room;
 
-	private Long avgWaitingTime;
-	private Long avgProcessingTime;
+	private OptionalDouble avgWaitingTime;
+	private OptionalDouble avgProcessingTime;
 }
diff --git a/src/main/java/nl/tudelft/queue/dto/view/statistics/session/GeneralSessionStatisticsViewDto.java b/src/main/java/nl/tudelft/queue/dto/view/statistics/session/GeneralSessionStatisticsViewDto.java
index f9ce36accc00a3027ff1506305bf10ac81489c37..44d1f441077ccbb8999ce34d1e54c12e632fc98f 100644
--- a/src/main/java/nl/tudelft/queue/dto/view/statistics/session/GeneralSessionStatisticsViewDto.java
+++ b/src/main/java/nl/tudelft/queue/dto/view/statistics/session/GeneralSessionStatisticsViewDto.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.queue.dto.view.statistics.session;
 
+import java.util.OptionalDouble;
+
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -31,8 +33,8 @@ public class GeneralSessionStatisticsViewDto {
 
 	private Long numEnqueued;
 
-	private Long avgWaitingTime;
+	private OptionalDouble avgWaitingTime;
 
-	private Long avgProcessingTime;
+	private OptionalDouble avgProcessingTime;
 
 }
diff --git a/src/main/java/nl/tudelft/queue/model/LabRequest.java b/src/main/java/nl/tudelft/queue/model/LabRequest.java
index 34ad99392cb849b4ea1d812a61e149c6e83f77d7..5561b521697905def7039ef77f255dfafa693e23 100644
--- a/src/main/java/nl/tudelft/queue/model/LabRequest.java
+++ b/src/main/java/nl/tudelft/queue/model/LabRequest.java
@@ -17,8 +17,6 @@
  */
 package nl.tudelft.queue.model;
 
-import static java.time.LocalDateTime.now;
-
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
@@ -112,30 +110,6 @@ public class LabRequest extends Request<Lab> {
 	@OneToMany(mappedBy = "request")
 	private List<Feedback> feedbacks = new ArrayList<>();
 
-	/**
-	 * Gets the waiting time in seconds experienced during this request. The waiting time is defined as the
-	 * time between the first time that the request was processed and the creation time of the request.
-	 *
-	 * @return The waiting time in seconds experienced during this request.
-	 */
-	public OptionalDouble waitingTime() {
-		if (getEventInfo().getFirstProcessedAt() == null || getCreatedAt() == null) {
-			return OptionalDouble.empty();
-		}
-
-		return OptionalDouble
-				.of(ChronoUnit.SECONDS.between(getCreatedAt(), getEventInfo().getFirstProcessedAt()));
-	}
-
-	/**
-	 * Alias for {@code sensibleWaitingTime(now())}
-	 *
-	 * @see #sensibleWaitingTime(LocalDateTime)
-	 */
-	public OptionalDouble sensibleWaitingTime() {
-		return sensibleWaitingTime(now());
-	}
-
 	/**
 	 * Gets the waiting time in seconds that is being experienced, or was experienced for this request. The
 	 * waiting time is defined differently depending on the specifics of the request:
@@ -150,13 +124,18 @@ public class LabRequest extends Request<Lab> {
 	 * effectiveEndTime.</li>
 	 * </ul>
 	 *
-	 * If this request has a timeslot which starts in the future, this method returns an empty optionaldouble.
-	 *
-	 * @param  effectiveEndTime the effective end time to use
+	 * If this request has a timeslot which starts in the future, this method returns an empty OptionalLong.
+	 * We also consider the end time of the session to override the effectiveEndTime so that viewing wait time
+	 * statistics for a session that occurs in the past is not skewed.
 	 *
-	 * @return                  The waiting time in seconds this request is experiencing or has experienced.
+	 * @param  effectiveEndTime The effective end time to collect wait time statistics. Usually this is the
+	 *                          present or the end of the lab. if computing bucketed statistics, you can put
+	 *                          it a time in the past.
+	 * @param  unit             The unit you want to compute this time difference in.
+	 * @return                  The waiting time in the desired unit.
 	 */
-	public OptionalDouble sensibleWaitingTime(LocalDateTime effectiveEndTime) {
+	public OptionalDouble waitTime(LocalDateTime effectiveEndTime,
+			ChronoUnit unit) {
 		LocalDateTime startTime;
 		if (getTimeSlot() == null) {
 			startTime = getCreatedAt();
@@ -171,12 +150,37 @@ public class LabRequest extends Request<Lab> {
 			endTime = getEventInfo().getFirstProcessedAt();
 		}
 
-		long time = ChronoUnit.SECONDS.between(startTime, endTime);
-		if (time < 0) {
+		return calculateTimeDifferenceWithUnit(startTime, endTime, unit);
+	}
+
+	/**
+	 * The processing time of a request. If a request has not yet processed, it is not considered and will
+	 * return an empty OptionalLong This also occurs when looking at something in the future. It contributes
+	 * to the calculation if it is currently being processed, or if it has been processed.
+	 *
+	 *
+	 * @param  effectiveEndTime The effective end time to collect wait time statistics. Usually this is the
+	 *                          present or the end of the lab. if computing bucketed statistics, you can put
+	 *                          it a time in the past.
+	 * @param  unit             The unit you want to compute this time difference in.
+	 * @return                  The processing time of the current request.
+	 */
+	public OptionalDouble processingTime(LocalDateTime effectiveEndTime,
+			ChronoUnit unit) {
+
+		final LocalDateTime startTime = getEventInfo().getFirstProcessedAt();
+
+		if (startTime == null)
 			return OptionalDouble.empty();
+
+		LocalDateTime endTime;
+		if (getEventInfo().getHandledAt() == null) {
+			endTime = effectiveEndTime;
+		} else {
+			endTime = getEventInfo().getHandledAt();
 		}
 
-		return OptionalDouble.of(time);
+		return calculateTimeDifferenceWithUnit(startTime, endTime, unit);
 	}
 
 	@Override
@@ -192,4 +196,23 @@ public class LabRequest extends Request<Lab> {
 	public Class<LabRequestViewDTO> viewClass() {
 		return LabRequestViewDTO.class;
 	}
+
+	/**
+	 * Calculate a time difference with a specified unit.
+	 *
+	 * @param  start The lower bound
+	 * @param  end   The upper bound
+	 * @param  unit  The unit you wish to retrieve the time difference in
+	 * @return       The time difference in the specified unit, if end < start, it will return an empty
+	 *               optional
+	 */
+	private OptionalDouble calculateTimeDifferenceWithUnit(LocalDateTime start, LocalDateTime end,
+			ChronoUnit unit) {
+		long time = unit.between(start, end);
+		if (time < 0) {
+			return OptionalDouble.empty();
+		}
+
+		return OptionalDouble.of(time);
+	}
 }
diff --git a/src/main/java/nl/tudelft/queue/model/TimeSlot.java b/src/main/java/nl/tudelft/queue/model/TimeSlot.java
index 1d745e1bed8ea6f0e8242d4c602e8f863e129a00..f5762364488295258d3bab86958f3f937b4bc2be 100644
--- a/src/main/java/nl/tudelft/queue/model/TimeSlot.java
+++ b/src/main/java/nl/tudelft/queue/model/TimeSlot.java
@@ -196,16 +196,4 @@ public class TimeSlot {
 						&& !ts.isFullAccordingToPercentage() && !ts.getSlot().closed())
 				.count() > slottedLab.getSlottedLabConfig().getPreviousEmptyAllowedThreshold();
 	}
-
-	/**
-	 * Counts the number of slots that are taken but did not finish processing. This is the count of how many
-	 * requests in a certain slot are pending.
-	 *
-	 * @return The number of requests that are pending.
-	 */
-	public int countPendingRequests() {
-		return (int) requests.stream()
-				.filter(r -> r.getEventInfo().getStatus().isPending())
-				.count();
-	}
 }
diff --git a/src/main/java/nl/tudelft/queue/model/labs/AbstractSlottedLab.java b/src/main/java/nl/tudelft/queue/model/labs/AbstractSlottedLab.java
index 82dd24bf48298b9ba9c5744768afa1ad28a92e05..c1a64128dd817987e0850797ca65bb877431dc7e 100644
--- a/src/main/java/nl/tudelft/queue/model/labs/AbstractSlottedLab.java
+++ b/src/main/java/nl/tudelft/queue/model/labs/AbstractSlottedLab.java
@@ -17,9 +17,14 @@
  */
 package nl.tudelft.queue.model.labs;
 
+import static java.time.LocalDateTime.now;
+
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Comparator;
 import java.util.List;
+import java.util.OptionalDouble;
 import java.util.stream.Stream;
 
 import jakarta.persistence.Embedded;
@@ -29,6 +34,7 @@ import jakarta.validation.constraints.NotNull;
 import lombok.*;
 import lombok.experimental.SuperBuilder;
 import nl.tudelft.queue.model.LabRequest;
+import nl.tudelft.queue.model.Request;
 import nl.tudelft.queue.model.TimeSlot;
 import nl.tudelft.queue.model.embeddables.SlottedLabConfig;
 
@@ -98,4 +104,37 @@ public abstract class AbstractSlottedLab<TS extends TimeSlot> extends Lab {
 		return slottedLabConfig.isConsecutive();
 	}
 
+	@Override
+	public OptionalDouble currentWaitingTime(LocalDateTime labEndTime, ChronoUnit unit) {
+
+		Stream<? extends TimeSlot> slots = getTimeSlots().stream();
+		OptionalDouble baseWaitTime;
+		LocalDateTime effectiveEndTime;
+
+		if (labEndTime.isBefore(now())) {
+			effectiveEndTime = labEndTime;
+			baseWaitTime = OptionalDouble.of(0);
+		} else {
+			slots = slots.filter(ts -> ts.getSlot().getOpensAt().isBefore(now()));
+			effectiveEndTime = now();
+			baseWaitTime = OptionalDouble.empty();
+		}
+
+		// Find the last started timeslot with pending requests, if any.
+		// Otherwise, find the last started timeslot with requests.
+		// Then pick the first created pending request, if any. Otherwise, pick the first created request.
+		return slots.max(Comparator.<TimeSlot>comparingInt(ts -> ts.hasPendingRequests() ? 1 : -1)
+				.thenComparingInt(ts -> ts.getRequests().size() > 0 ? 1 : -1)
+				.thenComparing(ts -> ts.getSlot().getOpensAt()))
+				.stream()
+				.flatMap(ts -> ts.getRequests().stream())
+				.max(Comparator
+						.<LabRequest>comparingInt(r -> r.getEventInfo().getStatus().isPending() ? 1 : -1)
+						.thenComparing(Comparator.nullsFirst(Comparator
+								.<LabRequest, LocalDateTime>comparing(Request::getCreatedAt)
+								.reversed())))
+				.map(r -> r.waitTime(effectiveEndTime, unit))
+				.orElse(baseWaitTime);
+	}
+
 }
diff --git a/src/main/java/nl/tudelft/queue/model/labs/Lab.java b/src/main/java/nl/tudelft/queue/model/labs/Lab.java
index d5be18fd5d41dcc9ec976fbe5abf5001b0b8c484..09ee2598abf42e17c3f63284787950513f7f6d3a 100644
--- a/src/main/java/nl/tudelft/queue/model/labs/Lab.java
+++ b/src/main/java/nl/tudelft/queue/model/labs/Lab.java
@@ -17,6 +17,10 @@
  */
 package nl.tudelft.queue.model.labs;
 
+import static java.time.LocalDateTime.now;
+
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -123,4 +127,26 @@ public abstract class Lab extends QueueSession<LabRequest> {
 	protected boolean allowsRequest(LabRequest request) {
 		return allowedRequests.contains(AllowedRequest.of(request.getAssignment(), request.getRequestType()));
 	}
+
+	public OptionalDouble currentWaitingTime(LocalDateTime labEndTime, ChronoUnit unit) {
+
+		if (labEndTime.isBefore(now())) {
+			// Lab is over, display waiting time of current requests or else 0
+			return getPendingRequests().stream()
+					.min(Comparator.comparing(LabRequest::getCreatedAt))
+					.map(r -> r.waitTime(labEndTime, unit))
+					.orElse(OptionalDouble.of(0));
+		} else {
+			// Lab is running. Get the waiting time of the oldest pending request.
+			// If nothing is pending, report the waiting time of the last handled request.
+			// If nothing was handled, report no waiting time.
+			return getPendingRequests().stream()
+					.min(Comparator.comparing(LabRequest::getCreatedAt))
+					.map(r -> r.waitTime(now(), unit))
+					.orElseGet(() -> getHandled().stream()
+							.max(Comparator.comparing(LabRequest::getCreatedAt))
+							.map(r -> r.waitTime(now(), unit))
+							.orElse(OptionalDouble.empty()));
+		}
+	}
 }
diff --git a/src/main/java/nl/tudelft/queue/service/EditionStatusService.java b/src/main/java/nl/tudelft/queue/service/EditionStatusService.java
index 9bc1f6ef0866cc7ade0e45a4b01a174dbd1c04af..107b98e0dd07f6299bad0c7edb2a22f2607dc1d0 100644
--- a/src/main/java/nl/tudelft/queue/service/EditionStatusService.java
+++ b/src/main/java/nl/tudelft/queue/service/EditionStatusService.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.queue.service;
 
+import static java.time.LocalDateTime.now;
 import static java.time.temporal.ChronoField.SECOND_OF_DAY;
 
 import java.time.LocalDateTime;
@@ -37,11 +38,11 @@ import nl.tudelft.labracore.api.dto.PersonSummaryDTO;
 import nl.tudelft.labracore.api.dto.RoomDetailsDTO;
 import nl.tudelft.queue.cache.PersonCacheManager;
 import nl.tudelft.queue.cache.RoomCacheManager;
-import nl.tudelft.queue.cache.SessionCacheManager;
 import nl.tudelft.queue.dto.view.statistics.AssignmentCountStatisticsViewDto;
 import nl.tudelft.queue.dto.view.statistics.AssistantRatingViewDto;
 import nl.tudelft.queue.dto.view.statistics.LabStatisticsViewDto;
 import nl.tudelft.queue.model.LabRequest;
+import nl.tudelft.queue.model.QueueSession;
 import nl.tudelft.queue.model.Request;
 import nl.tudelft.queue.model.enums.RequestType;
 import nl.tudelft.queue.model.labs.Lab;
@@ -56,8 +57,6 @@ public class EditionStatusService {
 
 	private final LabRequestRepository rr;
 
-	private final SessionCacheManager sCache;
-
 	private final PersonCacheManager pCache;
 
 	private final FeedbackService fs;
@@ -319,88 +318,47 @@ public class EditionStatusService {
 	}
 
 	/**
-	 * See {@link #averageWaitingTime(List, ChronoUnit, LocalDateTime)} for complete description.
+	 * Calculate average wait time for a list of requests.
 	 *
-	 * @param  requests The lists of requests to consider
-	 * @return          The average waiting time for these requests
+	 * @param  requests The list of requests to consider for the wait time calculation.
+	 * @param  unit     The {@link ChronoUnit} to calculate the average wait time in.
+	 * @return          The average wait time in the given unit. Can be none if no qualifying requests are
+	 *                  present.
 	 */
-	public Long averageWaitingTime(List<LabRequest> requests) {
-		return averageWaitingTime(requests, ChronoUnit.MILLIS, LocalDateTime.now());
-	}
+	public OptionalDouble averageWaitingTime(List<LabRequest> requests,
+			ChronoUnit unit) {
 
-	/**
-	 * See {@link #averageProcessingTime(List, ChronoUnit, LocalDateTime)} for complete description.
-	 *
-	 * @param  requests The lists of requests to consider
-	 * @return          The average processing time for these requests
-	 */
-	public Long averageProcessingTime(List<LabRequest> requests) {
-		return averageProcessingTime(requests, ChronoUnit.MILLIS, LocalDateTime.now());
-	}
+		Map<Long, LocalDateTime> effectiveEndTimes = calculateEffectiveEndTimeForRequestStatistics(requests);
 
-	/**
-	 * Calculates the average waiting time over all requests that are being processed or are already
-	 * processed.
-	 *
-	 * Note: for timeslots, we take the start of the timeslot as the start of the waiting period, whereas if
-	 * there is no timeslot, we take the createdAt time.
-	 *
-	 * @param  requests      The list of requests to calculate over.
-	 * @param  unit          The unit to calculate the average time into.
-	 * @param  referenceTime For requests that have not been processed yet, we still want to calculate the
-	 *                       waiting time. Furthermore, sometimes we want to calculate how long the average
-	 *                       time was in the perspective of an earlier time instead of now.
-	 * @return               The average time between creating a request and a TA starting to process it.
-	 */
-	public Long averageWaitingTime(List<LabRequest> requests, ChronoUnit unit, LocalDateTime referenceTime) {
-		return (long) requests
+		return requests
 				.stream()
-				.mapToLong(r -> {
-					LocalDateTime startTime = (r.getTimeSlot() != null)
-							? r.getTimeSlot().getSlot().getOpensAt()
-							: r.getCreatedAt();
-
-					if (referenceTime.isBefore(startTime)) {
-						return 0L;
-					}
-
-					return unit.between(startTime,
-							min(r.getEventInfo().getFirstProcessedAt(), referenceTime));
+				.flatMapToDouble(r -> {
+					LocalDateTime effectiveEndTime = effectiveEndTimes.getOrDefault(r.getId(), now());
+					return r.waitTime(effectiveEndTime, unit).stream();
 				})
-				.average().orElse(0.0);
+				.average();
 	}
 
 	/**
-	 * Calculates the average processing time (the time between a TA starting to process the student and the
-	 * request being handled) over the following types of requests
+	 * Calculate average processing time for a list of requests.
 	 *
-	 * <li>Requests that have been handled</li>
-	 * <li>Requests that are currently being handled (The time until now is taken in this case).</li>
-	 *
-	 * @param  requests      The list of requests to calculate over.
-	 * @param  unit          The unit to calculate the average time into.
-	 * @param  referenceTime For requests that have not been handled yet, we still want to calculate the
-	 *                       average processing time. Furthermore, sometimes we want to calculate the average
-	 *                       time from the perspective of an earlier time.
-	 * @return               The average time between processing a request and it being handled.
+	 * @param  requests The list of requests to consider for the average processing time calculation.
+	 * @param  unit     The {@link ChronoUnit} to calculate the average wait time in.
+	 * @return          The average processing time in the given unit. Can be none if no qualifying requests
+	 *                  are present.
 	 */
-	public Long averageProcessingTime(List<LabRequest> requests, ChronoUnit unit,
-			LocalDateTime referenceTime) {
-
-		return (long) requests.stream()
-				.filter(r -> r.getEventInfo().getFirstProcessedAt() != null)
-				.mapToLong(r -> {
-					final LocalDateTime handledAt = r.getEventInfo().getHandledAt();
-					final LocalDateTime firstProcessedAt = r.getEventInfo().getFirstProcessedAt();
+	public OptionalDouble averageProcessingTime(List<LabRequest> requests,
+			ChronoUnit unit) {
 
-					if (referenceTime.isBefore(firstProcessedAt)) {
-						return 0L;
-					}
+		Map<Long, LocalDateTime> effectiveEndTimes = calculateEffectiveEndTimeForRequestStatistics(requests);
 
-					return unit.between(firstProcessedAt, min(handledAt, referenceTime));
+		return requests
+				.stream()
+				.flatMapToDouble(r -> {
+					LocalDateTime effectiveEndTime = effectiveEndTimes.getOrDefault(r.getId(), now());
+					return r.processingTime(effectiveEndTime, unit).stream();
 				})
-				.average()
-				.orElse(0.0);
+				.average();
 	}
 
 	/**
@@ -461,17 +419,15 @@ public class EditionStatusService {
 	 */
 	public Map<String, LabStatisticsViewDto> countWaitProcessingTimePerLab(List<LabRequest> requests) {
 
-		final LocalDateTime now = LocalDateTime.now();
-
 		Map<String, List<LabRequest>> groupedLabRequests = groupRequestsByLab(requests);
 
 		return new TreeMap<>(groupedLabRequests.entrySet().stream()
 				.collect(Collectors.toMap(
 						Map.Entry::getKey,
 						entry -> LabStatisticsViewDto.builder()
-								.avgWaitingTime(averageWaitingTime(entry.getValue(), ChronoUnit.MINUTES, now))
+								.avgWaitingTime(averageWaitingTime(entry.getValue(), ChronoUnit.MINUTES))
 								.avgProcessingTime(
-										averageProcessingTime(entry.getValue(), ChronoUnit.MINUTES, now))
+										averageProcessingTime(entry.getValue(), ChronoUnit.MINUTES))
 								.build())));
 	}
 
@@ -501,6 +457,32 @@ public class EditionStatusService {
 						Map.Entry::getValue));
 	}
 
+	/**
+	 * Used to calculate the effective end time for a list of requests, used for statistics throughout the
+	 * app.
+	 *
+	 * @param  requests The list of requests to calculate the effective end time for.
+	 * @return          A map of requests to their effective end time.
+	 */
+	public Map<Long, LocalDateTime> calculateEffectiveEndTimeForRequestStatistics(List<LabRequest> requests) {
+		return requests.stream()
+				.collect(Collectors.toMap(
+						Request::getId,
+						request -> calculateEffectiveEndTimeForLab(request.getSession())));
+	}
+
+	/**
+	 * The calculation for the 'effective end time' used in many statistics. Basically whether we want a live
+	 * representation or a representation which considers the chosen statistic in the past.
+	 *
+	 * @param  qSession The session in question
+	 * @return          min(session end time, now)
+	 */
+	private LocalDateTime calculateEffectiveEndTimeForLab(QueueSession<?> qSession) {
+		LocalDateTime endTime = sessionService.getSessionEndTime(qSession);
+		return min(endTime, now());
+	}
+
 	/**
 	 * Returns the min of two LocalDateTime instances. If one instance is null, it will return the other one
 	 *
@@ -511,11 +493,13 @@ public class EditionStatusService {
 	 */
 	private LocalDateTime min(LocalDateTime d1, LocalDateTime d2) {
 		if (d1 == null && d2 == null)
-			throw new IllegalArgumentException("This should not happen");
+			throw new IllegalArgumentException("One of the arguments needs to be non-null.");
 		if (d1 == null)
 			return d2;
 		if (d2 == null)
 			return d1;
+
 		return d1.isBefore(d2) ? d1 : d2;
 	}
+
 }
diff --git a/src/main/java/nl/tudelft/queue/service/LabService.java b/src/main/java/nl/tudelft/queue/service/LabService.java
index b5c10313245c8b01e98dee130c10762e1948cea9..85b6e91cb8c44cb4e9e8e4d53044ab743afbc03e 100644
--- a/src/main/java/nl/tudelft/queue/service/LabService.java
+++ b/src/main/java/nl/tudelft/queue/service/LabService.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.Resource;
@@ -68,7 +67,6 @@ import nl.tudelft.queue.model.labs.AbstractSlottedLab;
 import nl.tudelft.queue.model.labs.CapacitySession;
 import nl.tudelft.queue.model.labs.ExamLab;
 import nl.tudelft.queue.model.labs.Lab;
-import nl.tudelft.queue.model.labs.RegularLab;
 import nl.tudelft.queue.model.misc.Presentation;
 import nl.tudelft.queue.repository.LabRepository;
 import nl.tudelft.queue.repository.LabRequestConstraintRepository;
@@ -90,9 +88,6 @@ public class LabService {
 	@Autowired
 	private EditionCollectionCacheManager ecCache;
 
-	@Autowired
-	private SessionCacheManager sCache;
-
 	@Autowired
 	private AssignmentCacheManager aCache;
 
@@ -111,9 +106,6 @@ public class LabService {
 	@Autowired
 	private RequestTableService rts;
 
-	@Autowired
-	private TimeSlotService tss;
-
 	@Autowired
 	private LabRepository lr;
 
@@ -140,6 +132,7 @@ public class LabService {
 
 	@Autowired
 	private SessionService sessionService;
+
 	@Autowired
 	private SessionCacheManager sessionCache;
 
@@ -562,93 +555,6 @@ public class LabService {
 		}
 	}
 
-	public OptionalDouble currentWaitingTime(Lab lab) {
-		if (lab instanceof RegularLab) {
-			return currentWaitingTime((RegularLab) lab);
-		} else if (lab instanceof AbstractSlottedLab<?>) {
-			return currentWaitingTime((AbstractSlottedLab<? extends TimeSlot>) lab);
-		}
-		return OptionalDouble.empty();
-	}
-
-	public OptionalDouble currentWaitingTime(AbstractSlottedLab<? extends TimeSlot> lab) {
-		var labEndTime = sessionService.getSessionDTOFromSession(lab).getEndTime();
-		Stream<? extends TimeSlot> slots = lab.getTimeSlots().stream();
-		OptionalDouble baseWaitTime;
-		LocalDateTime effectiveEndTime;
-
-		if (labEndTime.isBefore(now())) {
-			effectiveEndTime = labEndTime;
-			baseWaitTime = OptionalDouble.of(0);
-		} else {
-			slots = slots.filter(ts -> ts.getSlot().getOpensAt().isBefore(now()));
-			effectiveEndTime = now();
-			baseWaitTime = OptionalDouble.empty();
-		}
-
-		// Find the last started timeslot with pending requests, if any.
-		// Otherwise, find the last started timeslot with requests.
-		// Then pick the first created pending request, if any. Otherwise, pick the first created request.
-		return slots.max(Comparator.<TimeSlot>comparingInt(ts -> ts.hasPendingRequests() ? 1 : -1)
-				.thenComparingInt(ts -> ts.getRequests().size() > 0 ? 1 : -1)
-				.thenComparing(ts -> ts.getSlot().getOpensAt()))
-				.stream()
-				.flatMap(ts -> ts.getRequests().stream())
-				.max(Comparator
-						.<LabRequest>comparingInt(r -> r.getEventInfo().getStatus().isPending() ? 1 : -1)
-						.thenComparing(Comparator.nullsFirst(Comparator
-								.<LabRequest, LocalDateTime>comparing(Request::getCreatedAt)
-								.reversed())))
-				.map(r -> r.sensibleWaitingTime(effectiveEndTime))
-				.orElse(baseWaitTime);
-
-	}
-
-	public OptionalDouble currentWaitingTime(RegularLab lab) {
-		var labEndTime = sessionService.getSessionDTOFromSession(lab).getEndTime();
-
-		if (labEndTime.isBefore(LocalDateTime.now())) {
-			// Lab is over, display waiting time of current requests or else 0
-			return lab.getPendingRequests().stream()
-					.min(Comparator.comparing(LabRequest::getCreatedAt))
-					.map(r -> r.sensibleWaitingTime(labEndTime))
-					.orElse(OptionalDouble.of(0));
-		} else {
-			// Lab is running. Get the waiting time of the oldest pending request.
-			// If nothing is pending, report the waiting time of the last handled request.
-			// If nothing was handled, report no waiting time.
-			return lab.getPendingRequests().stream()
-					.min(Comparator.comparing(LabRequest::getCreatedAt))
-					.map(LabRequest::sensibleWaitingTime)
-					.orElseGet(() -> lab.getHandled().stream()
-							.max(Comparator.comparing(LabRequest::getCreatedAt))
-							.map(LabRequest::sensibleWaitingTime)
-							.orElse(OptionalDouble.empty()));
-		}
-
-	}
-
-	/**
-	 * Gets the average waiting time experienced by students in this lab over the last hour. If the lab is
-	 * over, this returns the average waiting time over the entire lab instead.
-	 *
-	 * @return The average waiting time if one can be calculated, for fresh labs this is empty.
-	 */
-	public OptionalDouble averageWaitingTime(Lab lab) {
-		var labEndTime = sessionService.getSessionDTOFromSession(lab).getEndTime();
-		if (labEndTime.isBefore(now())) {
-			// past session, give average over the session
-			return lab.getHandled().stream()
-					.flatMapToDouble(r -> r.sensibleWaitingTime(labEndTime).stream())
-					.average();
-		} else {
-			return lab.getHandled().stream()
-					.filter(r -> r.getEventInfo().getLastEventAt().isAfter(now().minusHours(1)))
-					.flatMapToDouble(r -> r.sensibleWaitingTime().stream())
-					.average();
-		}
-	}
-
 	public boolean allowsRequest(QueueSession<?> session, Request<?> request) {
 		if (!labRequestConstraintService.allowsRequest(session.getConstraints(), request)
 				&& Objects.equals(request.getSession().getId(), session.getId())) {
diff --git a/src/main/java/nl/tudelft/queue/service/SessionService.java b/src/main/java/nl/tudelft/queue/service/SessionService.java
index 83d4f4062be3e019e7104fb342bd2b42180af9fb..71ae6b358dc72c00ea84356edf3ea66571b6c2ea 100644
--- a/src/main/java/nl/tudelft/queue/service/SessionService.java
+++ b/src/main/java/nl/tudelft/queue/service/SessionService.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.queue.service;
 
+import java.time.LocalDateTime;
 import java.util.*;
 
 import org.springframework.stereotype.Service;
@@ -107,4 +108,15 @@ public class SessionService {
 		SessionDetailsDTO session = getCoreSession(qSession.getSession());
 		return qSession.copyLabCreateDTO(session);
 	}
+
+	/**
+	 * End time for a core session.
+	 *
+	 * @param  qSession The session in question.
+	 * @return          The end time of the session
+	 */
+	public LocalDateTime getSessionEndTime(QueueSession<?> qSession) {
+		return getCoreSession(qSession.getSession()).getEndTime();
+	}
+
 }
diff --git a/src/main/java/nl/tudelft/queue/service/SessionStatusService.java b/src/main/java/nl/tudelft/queue/service/SessionStatusService.java
index f57508dcc2958e219c06e0a4e4acbc0cd5b2e3cd..823a06e40a1ae7fd0326d34ed46b717818e25b46 100644
--- a/src/main/java/nl/tudelft/queue/service/SessionStatusService.java
+++ b/src/main/java/nl/tudelft/queue/service/SessionStatusService.java
@@ -17,6 +17,8 @@
  */
 package nl.tudelft.queue.service;
 
+import static java.time.LocalDateTime.now;
+
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
@@ -76,6 +78,27 @@ public class SessionStatusService {
 
 	}
 
+	/**
+	 * Gets the average waiting time experienced by students in this lab. If the lab is over, this returns the
+	 * average waiting time over the entire lab instead.
+	 *
+	 * @return The average waiting time if one can be calculated, for fresh labs this is empty.
+	 */
+	public OptionalDouble averageWaitingTime(Lab qs) {
+		return ess.averageWaitingTime(qs.getRequests(), ChronoUnit.SECONDS);
+	}
+
+	/**
+	 * Gets the current waiting time of a lab. Calculated differently between regular and slotted labs.
+	 *
+	 * @param  lab The lab to calculate the current waiting time for.
+	 * @return     The current waiting time in seconds.
+	 */
+	public OptionalDouble currentWaitingTime(Lab lab) {
+		LocalDateTime labEndTime = sessionService.getSessionEndTime(lab);
+		return lab.currentWaitingTime(labEndTime, ChronoUnit.SECONDS);
+	}
+
 	/**
 	 * Method responsible for creating a list of dtos where each one represents a bucket containing
 	 * information about how many requests occured within that timespan. It also segregates between the
@@ -93,7 +116,8 @@ public class SessionStatusService {
 			Set<Long> editions,
 			long bucketSizeInMinutes) {
 
-		final BiFunction<List<LabRequest>, LocalDateTime, Map<String, Long>> bucketFunction = (labRequests,
+		final BiFunction<List<LabRequest>, LocalDateTime, Map<String, ? extends Number>> bucketFunction = (
+				labRequests,
 				bucketEnd) -> {
 
 			// bucket function does not consider `bucketEnd` since this is not a running statistic.
@@ -127,7 +151,8 @@ public class SessionStatusService {
 			Set<Long> editions,
 			long bucketSizeInMinutes) {
 
-		final BiFunction<List<LabRequest>, LocalDateTime, Map<String, Long>> bucketFunction = (labRequests,
+		final BiFunction<List<LabRequest>, LocalDateTime, Map<String, ? extends Number>> bucketFunction = (
+				labRequests,
 				bucketEnd) -> {
 			List<RoomDetailsDTO> rooms = labRequests.stream()
 					.filter(rq -> rq.getRoom() != null)
@@ -160,15 +185,17 @@ public class SessionStatusService {
 		final LocalDateTime now = LocalDateTime.now();
 
 		// running statistic which considers the last 1 hour to avoid outlier skewing.
-		BiFunction<List<LabRequest>, LocalDateTime, Map<String, Long>> bucketFunction = (labRequests,
+		BiFunction<List<LabRequest>, LocalDateTime, Map<String, ? extends Number>> bucketFunction = (
+				labRequests,
 				bucketEnd) -> {
-			List<LabRequest> requestsInTheLastThirtyMinutes = labRequests.stream()
+			List<LabRequest> requestsInTheLastHour = labRequests.stream()
 					.filter(rq -> rq.getCreatedAt().isAfter(now.minusHours(1L))).toList();
 			return Map.of(
 					"Average Wait Time",
-					ess.averageWaitingTime(requestsInTheLastThirtyMinutes, ChronoUnit.MINUTES, bucketEnd),
+					ess.averageWaitingTime(requestsInTheLastHour, ChronoUnit.MINUTES).orElse(0.0d),
+
 					"Average Processing Time",
-					ess.averageProcessingTime(requestsInTheLastThirtyMinutes, ChronoUnit.MINUTES, bucketEnd));
+					ess.averageProcessingTime(requestsInTheLastHour, ChronoUnit.MINUTES).orElse(0.0d));
 		};
 
 		return createBucketsForStatistic(qSession, editions, bucketSizeInMinutes, bucketFunction, true);
@@ -188,7 +215,7 @@ public class SessionStatusService {
 	private List<BucketStatisticsViewDto> createBucketsForStatistic(Lab qSession,
 			Set<Long> editions,
 			long bucketSizeInMinutes,
-			BiFunction<List<LabRequest>, LocalDateTime, Map<String, Long>> bucketFunction,
+			BiFunction<List<LabRequest>, LocalDateTime, Map<String, ? extends Number>> bucketFunction,
 			boolean runningStatistic) {
 		LocalDateTime now = LocalDateTime.now();
 		var requests = requestService.getLabRequestsForEditions(qSession.getRequests(), editions);
@@ -224,7 +251,8 @@ public class SessionStatusService {
 								.toList();
 					}
 
-					Map<String, Long> bucketData = bucketFunction.apply(requestsInBucket, bucketEnd);
+					Map<String, ? extends Number> bucketData = bucketFunction.apply(requestsInBucket,
+							bucketEnd);
 
 					String bucketLabel = bucketStart.format(dateFormat) +
 							" - " +
diff --git a/src/main/resources/static/js/chart_utils.js b/src/main/resources/static/js/chart_utils.js
index d4be8a536bf17103c5f8d47cf0907e9fd15144cd..2356876e24a553f1fa18eae48fcd3d083cb5fd06 100644
--- a/src/main/resources/static/js/chart_utils.js
+++ b/src/main/resources/static/js/chart_utils.js
@@ -17,6 +17,7 @@
  */
 
 let colorIdx = 0;
+const UNKNOWN = "Unknown";
 
 /**
  * Color-blind friendly random colors used in graphs.
@@ -74,6 +75,8 @@ function getColorForStatus(status) {
  * @returns {string} A string which has a human representation of the spanned time.
  */
 function msToHumanReadableTime(ms) {
+    if (!ms) return UNKNOWN;
+    ms = parseInt(ms);
     let seconds = (ms / 1000).toFixed(1);
     let minutes = (ms / (1000 * 60)).toFixed(1);
     let hours = (ms / (1000 * 60 * 60)).toFixed(1);
diff --git a/src/main/resources/static/js/lab_session_status_common.js b/src/main/resources/static/js/lab_session_status_common.js
index 63eb0b6946abe2c89bfed3a500fafe6456940955..aa6a14eb1da2971b705e77aa5b6856ce1b02324c 100644
--- a/src/main/resources/static/js/lab_session_status_common.js
+++ b/src/main/resources/static/js/lab_session_status_common.js
@@ -347,8 +347,8 @@ function updateLabTimeChart(canvas) {
 
         Object.entries(data).forEach(([labName, labStatusDto]) => {
             labels.push(labName);
-            avgWaitTimes.push(labStatusDto.avgWaitingTime);
-            avgProcessingTimes.push(labStatusDto.avgProcessingTime);
+            avgWaitTimes.push(labStatusDto.avgWaitingTime ?? 0);
+            avgProcessingTimes.push(labStatusDto.avgProcessingTime ?? 0);
         });
 
         if (actLabTimeChart != null) {
diff --git a/src/main/resources/static/js/session_status.js b/src/main/resources/static/js/session_status.js
index 42143ff40cca6babf51b2694d5978e04a91cb61e..65db5c729a9bff958e3e4a8d63a51bbba9e3855e 100644
--- a/src/main/resources/static/js/session_status.js
+++ b/src/main/resources/static/js/session_status.js
@@ -140,11 +140,7 @@ function updateGeneralInformation(infoCards) {
         $(infoCards).find("#card-question-count").html(numQuestions);
         $(infoCards).find("#card-submission-count").html(numSubmissions);
         $(infoCards).find("#card-enqueued-count").html(data["numEnqueued"]);
-        $(infoCards)
-            .find("#card-waiting-time")
-            .html(msToHumanReadableTime(parseInt(data["avgWaitingTime"])));
-        $(infoCards)
-            .find("#card-processing-time")
-            .html(msToHumanReadableTime(parseInt(data["avgProcessingTime"])));
+        $(infoCards).find("#card-waiting-time").html(msToHumanReadableTime(data["avgWaitingTime"]));
+        $(infoCards).find("#card-processing-time").html(msToHumanReadableTime(data["avgProcessingTime"]));
     };
 }
diff --git a/src/main/resources/templates/edition/view/status.html b/src/main/resources/templates/edition/view/status.html
index 21b528b82df5f8ca1dd2fd83458a9f39aee8a4c6..74326c2e4541c6acc9bfe8f719c0825892e75ad6 100644
--- a/src/main/resources/templates/edition/view/status.html
+++ b/src/main/resources/templates/edition/view/status.html
@@ -150,11 +150,11 @@
                                 <td id="lab-static-room">N.A.</td>
                             </tr>
                             <tr>
-                                <td>Average waiting time for the last hour</td>
+                                <td>Average waiting time</td>
                                 <td id="lab-static-avgWaitingTime">N.A.</td>
                             </tr>
                             <tr>
-                                <td>Average processing time in the last hour</td>
+                                <td>Average processing time</td>
                                 <td id="lab-static-avgProcessingTime">N.A.</td>
                             </tr>
                         </table>
diff --git a/src/main/resources/templates/lab/view/components/lab-info.html b/src/main/resources/templates/lab/view/components/lab-info.html
index 8bddb4f9b35985f63156ac63ccac9232cb4e3c84..3eefd90348f263de2f01d03a26e23f23b9e6d633 100644
--- a/src/main/resources/templates/lab/view/components/lab-info.html
+++ b/src/main/resources/templates/lab/view/components/lab-info.html
@@ -163,13 +163,14 @@
                     </dd>
 
                     <dt class="fw-500 mt-3">Waiting time</dt>
-                    <dd th:with="avg = ${@labService.averageWaitingTime(qSession.data)}, cur = ${@labService.currentWaitingTime(qSession.data)}">
+                    <dd
+                        th:with="avg = ${@sessionStatusService.averageWaitingTime(qSession.data)}, cur = ${@sessionStatusService.currentWaitingTime(qSession.data)}">
                         <th:block th:if="${avg.isPresent() || cur.isPresent()}">
                             <th:block th:if="${avg.isPresent()}">
                                 <span th:text="|${T(java.lang.Math).round(avg.getAsDouble() / 60)} minutes (average)|"></span>
                                 <div class="tooltip">
                                     <button class="tooltip__control fa-solid fa-question"></button>
-                                    <p role="tooltip">Computed as the average waiting time of archived requests in the past hour.</p>
+                                    <p role="tooltip">Computed as the average waiting time of across all requests in the lab.</p>
                                 </div>
                             </th:block>
                             <span th:unless="${avg.isPresent()}">Unknown (average)</span>
diff --git a/src/test/java/nl/tudelft/queue/model/LabTest.java b/src/test/java/nl/tudelft/queue/model/LabTest.java
index 1726f34ebfa33000752f17a4842551d932b93865..673decdc5eadcc5e69c34574bc8543d56b31d50b 100644
--- a/src/test/java/nl/tudelft/queue/model/LabTest.java
+++ b/src/test/java/nl/tudelft/queue/model/LabTest.java
@@ -30,7 +30,6 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.ApplicationContext;
 
 import jakarta.transaction.Transactional;
 import nl.tudelft.queue.model.embeddables.AllowedRequest;
@@ -41,8 +40,7 @@ import nl.tudelft.queue.model.enums.RequestType;
 import nl.tudelft.queue.model.labs.Lab;
 import nl.tudelft.queue.model.labs.RegularLab;
 import nl.tudelft.queue.model.labs.SlottedLab;
-import nl.tudelft.queue.service.LabService;
-import nl.tudelft.queue.service.SessionService;
+import nl.tudelft.queue.service.SessionStatusService;
 import test.TestDatabaseLoader;
 import test.labracore.SessionApiMocker;
 import test.test.TestQueueApplication;
@@ -61,16 +59,11 @@ public class LabTest {
 	@Autowired
 	private SessionApiMocker sMock;
 
-	@Autowired
-	private ApplicationContext applicationContext;
-
 	@Autowired
 	private TestDatabaseLoader db;
 
 	@Autowired
-	private SessionService sessionService;
-	@Autowired
-	private LabService labService;
+	private SessionStatusService sessionStatusService;
 
 	@BeforeEach
 	void setUp() {
@@ -103,7 +96,7 @@ public class LabTest {
 				.build();
 
 		request3 = LabRequest.builder()
-				.id(8932L)
+				.id(8933L)
 				.requestType(QUESTION)
 				.assignment(56582L)
 				.comment("hdsada")
@@ -132,6 +125,10 @@ public class LabTest {
 				.deletedAt(null)
 				.requests(List.of(request1, request2, request3))
 				.build();
+
+		request1.setSession(lab1);
+		request2.setSession(lab1);
+		request3.setSession(lab1);
 	}
 
 	@Test
@@ -250,13 +247,13 @@ public class LabTest {
 
 	@Test
 	void averageWaitingTimeAveragesOverHandled() {
-		assertThat(labService.averageWaitingTime(lab1)).isPresent()
-				.hasValueCloseTo(60.0, Offset.offset(0.005));
+		assertThat(sessionStatusService.averageWaitingTime(lab1)).isPresent()
+				.hasValueCloseTo(30.0, Offset.offset(0.005));
 	}
 
 	@Test
 	void currentWaitingTimeWorksOnLastPending() {
-		assertThat(labService.currentWaitingTime(lab1)).isPresent()
+		assertThat(sessionStatusService.currentWaitingTime(lab1)).isPresent()
 				.hasValueCloseTo(30.0, Offset.offset(0.005));
 	}
 
diff --git a/src/test/java/nl/tudelft/queue/model/RequestTest.java b/src/test/java/nl/tudelft/queue/model/RequestTest.java
index 9d749a63ecabf176d6fe875b5c443cb55ed358b2..035fab1e8924451584a478038be8160c8085827a 100644
--- a/src/test/java/nl/tudelft/queue/model/RequestTest.java
+++ b/src/test/java/nl/tudelft/queue/model/RequestTest.java
@@ -17,13 +17,9 @@
  */
 package nl.tudelft.queue.model;
 
-import static org.assertj.core.api.Assertions.assertThat;
-
 import java.time.LocalDateTime;
 
-import org.assertj.core.data.Offset;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
 
 import nl.tudelft.queue.model.embeddables.RequestEventInfo;
 
@@ -44,23 +40,4 @@ public class RequestTest {
 				.build();
 	}
 
-	@Test
-	void waitingTimeCalculatesDifferenceBetweenCreatedAtAndFirstProcessedTime() {
-		assertThat(request.waitingTime()).isPresent()
-				.hasValueCloseTo(30.0, Offset.offset(0.005));
-	}
-
-	@Test
-	void waitingTimeCalculationFailsForNullCreatedAt() {
-		request.setCreatedAt(null);
-
-		assertThat(request.waitingTime()).isEmpty();
-	}
-
-	@Test
-	void waitingTimeCalculationFailsForNullFirstProcessedAt() {
-		request.getEventInfo().setFirstProcessedAt(null);
-
-		assertThat(request.waitingTime()).isEmpty();
-	}
 }
diff --git a/src/test/java/nl/tudelft/queue/service/EditionStatusServiceTest.java b/src/test/java/nl/tudelft/queue/service/EditionStatusServiceTest.java
index 71be45e54d85a953a68325dd308ec2144d049250..96f51fff72dc626ac4004891da61b57f4966fa77 100644
--- a/src/test/java/nl/tudelft/queue/service/EditionStatusServiceTest.java
+++ b/src/test/java/nl/tudelft/queue/service/EditionStatusServiceTest.java
@@ -17,6 +17,7 @@
  */
 package nl.tudelft.queue.service;
 
+import static java.time.LocalDateTime.now;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.time.LocalDateTime;
@@ -150,8 +151,8 @@ public class EditionStatusServiceTest {
 			new RoomDetailsDTO().id(32L).name("R1")
 	};
 	private SessionDetailsDTO[] sessions = {
-			new SessionDetailsDTO().id(34L).start(LocalDateTime.of(2023, 1, 1, 0, 0, 0))
-					.endTime(LocalDateTime.of(2023, 1, 1, 0, 0, 2))
+			new SessionDetailsDTO().id(34L).start(LocalDateTime.now().minusHours(1L))
+					.endTime(LocalDateTime.now().plusHours(3L))
 	};
 
 	@BeforeEach
@@ -456,8 +457,14 @@ public class EditionStatusServiceTest {
 
 	@Test
 	void averageWaitingProcessingTimeEmptyTestShouldYieldZero() {
-		assertThat(ess.averageWaitingTime(List.of())).isEqualTo(0L);
-		assertThat(ess.averageProcessingTime(List.of())).isEqualTo(0L);
+		assertThat(ess.averageWaitingTime(List.of(), ChronoUnit.SECONDS)).isEqualTo(OptionalDouble.empty());
+		assertThat(ess.averageWaitingTime(List.of(), ChronoUnit.MILLIS)).isEqualTo(OptionalDouble.empty());
+		assertThat(ess.averageWaitingTime(List.of(), ChronoUnit.MINUTES)).isEqualTo(OptionalDouble.empty());
+		assertThat(ess.averageProcessingTime(List.of(), ChronoUnit.SECONDS))
+				.isEqualTo(OptionalDouble.empty());
+		assertThat(ess.averageProcessingTime(List.of(), ChronoUnit.MILLIS)).isEqualTo(OptionalDouble.empty());
+		assertThat(ess.averageProcessingTime(List.of(), ChronoUnit.MINUTES))
+				.isEqualTo(OptionalDouble.empty());
 
 	}
 
@@ -466,52 +473,50 @@ public class EditionStatusServiceTest {
 		LocalDateTime now = LocalDateTime.now();
 
 		request1.getEventInfo().setFirstProcessedAt(now.minusSeconds(10L));
-		Long result = ess.averageProcessingTime(List.of(request1));
+		OptionalDouble result = ess.averageProcessingTime(List.of(request1), ChronoUnit.SECONDS);
 
-		assertThat(result).isCloseTo(10L * 1000, Percentage.withPercentage(5)); // 5% tolerance = 500ms
+		assertThat(result.getAsDouble()).isCloseTo(10L, Percentage.withPercentage(15));
 	}
 
 	@Test
 	void averageProcessingTimeNoTimeAssignedTest() {
 		request1.getEventInfo().setStatus(RequestStatus.APPROVED);
 		rr.save(request1);
-		Long result = ess.averageProcessingTime(List.of(request1));
+		OptionalDouble result = ess.averageProcessingTime(List.of(request1), ChronoUnit.MILLIS);
 
-		assertThat(result).isEqualTo(0L);
+		assertThat(result).isEqualTo(OptionalDouble.empty());
 
 	}
 
 	@Test
-	void averageProcessingTimeNotHandledButIsInTheFutureShouldReturnZero() {
-		LocalDateTime now = LocalDateTime.now();
+	void averageProcessingTimeHandledButIsInTheFutureShouldReturnZero() {
 
-		request1.getEventInfo().setFirstProcessedAt(now.plusSeconds(1L));
-		Long result = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES, now);
+		request1.getEventInfo().setFirstProcessedAt(now().plusSeconds(1L));
+		OptionalDouble result = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES);
 
-		assertThat(result).isEqualTo(0L);
+		assertThat(result.getAsDouble()).isEqualTo(0.0d);
 
 	}
 
 	@Test
 	void averageProcessingTimeTest() {
+
 		final LocalDateTime now = LocalDateTime.now();
 
 		request1.getEventInfo().setStatus(RequestStatus.APPROVED);
 		request1.getEventInfo().setFirstProcessedAt(now.minusSeconds(12L));
 		request1.getEventInfo().setHandledAt(now);
 		rr.save(request1);
-		Long res1 = ess.averageProcessingTime(List.of(request1));
-		Long res2 = ess.averageProcessingTime(List.of(request1), ChronoUnit.SECONDS, now);
-		Long res3 = ess.averageProcessingTime(List.of(request1), ChronoUnit.SECONDS, now.minusSeconds(6L));
-		Long res4 = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES, now);
+		OptionalDouble res1 = ess.averageProcessingTime(List.of(request1), ChronoUnit.MILLIS);
+		OptionalDouble res2 = ess.averageProcessingTime(List.of(request1), ChronoUnit.SECONDS);
+		OptionalDouble res4 = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES);
 		request1.getEventInfo().setFirstProcessedAt(now.minusMinutes(2L));
-		Long res5 = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES, now.minusMinutes(1L));
+		OptionalDouble res5 = ess.averageProcessingTime(List.of(request1), ChronoUnit.MINUTES);
 
-		assertThat(res1).isEqualTo(12L * 1000L);
-		assertThat(res2).isEqualTo(12L);
-		assertThat(res3).isEqualTo(6L);
-		assertThat(res4).isEqualTo(0L);
-		assertThat(res5).isEqualTo(1L);
+		assertThat(res1.getAsDouble()).isEqualTo(12L * 1000L);
+		assertThat(res2.getAsDouble()).isEqualTo(12L);
+		assertThat(res4.getAsDouble()).isEqualTo(0L);
+		assertThat(res5.getAsDouble()).isEqualTo(2L);
 
 	}
 
@@ -520,15 +525,15 @@ public class EditionStatusServiceTest {
 		request4.getEventInfo().setStatus(RequestStatus.APPROVED);
 		request4.getEventInfo().setFirstProcessedAt(LocalDateTime.of(2023, 1, 1, 0, 0, 7));
 		rr.save(request4);
-		Long result = ess.averageWaitingTime(List.of(request4));
-		assertThat(result).isEqualTo(1L * 1000);
+		OptionalDouble result = ess.averageWaitingTime(List.of(request4), ChronoUnit.MILLIS);
+		assertThat(result.getAsDouble()).isEqualTo(1L * 1000);
 	}
 
 	@Test
 	void createBucketsOverCourseTest() {
 		TreeSet<Long> result = ess.createBucketsOverCourse(List.of(lab), 1);
+		assertThat(result).hasSize(2);
 
-		assertThat(result).containsExactlyInAnyOrder(0L, 2L);
 	}
 
 	@Test
diff --git a/src/test/java/nl/tudelft/queue/service/SessionStatusServiceTest.java b/src/test/java/nl/tudelft/queue/service/SessionStatusServiceTest.java
index f452e3c04d3761648ab5475e72f4ee74677eea02..83134046d79931d49ede84aaf7b906ecf64b76ed 100644
--- a/src/test/java/nl/tudelft/queue/service/SessionStatusServiceTest.java
+++ b/src/test/java/nl/tudelft/queue/service/SessionStatusServiceTest.java
@@ -109,7 +109,9 @@ public class SessionStatusServiceTest {
 		var sut = sessionStatusService.createRequestDistribution(oopNowRegularLab1, new HashSet<>(), 5);
 		assertThat(sut).hasSize(1);
 		var numOfResults = sut.stream()
-				.map(bucket -> bucket.getBucketData().values().stream().reduce(0L, Long::sum))
+				.map(bucket -> bucket.getBucketData().values().stream()
+						.mapToLong(Number::longValue)
+						.reduce(0L, Long::sum))
 				.reduce(0L, Long::sum);
 		assertThat(numOfResults).isEqualTo(50);
 	}