diff --git a/src/utils/diagnostics/stopwatch.ts b/src/utils/diagnostics/stopwatch.ts
index ad0e9a4..9138328 100644
--- a/src/utils/diagnostics/stopwatch.ts
+++ b/src/utils/diagnostics/stopwatch.ts
@@ -1,66 +1,140 @@
+/**
+ * A callback type for when a {@link Stopwatch} is started.
+ */
 interface StartCallback {
-    (currentDate: Date, stopwatch: Stopwatch): void;
+    /**
+     * @param date - The date when the {@link Stopwatch} was started.
+     * @param stopwatch - The {@link Stopwatch} instance.
+     */
+    (date: Date, stopwatch: Stopwatch): void;
 }
 
+/**
+ * A callback type for when a {@link Stopwatch} is stopped.
+ */
 interface StopCallback {
-    (elapsedMilliseconds: number, currentDate: Date, stopwatch: Stopwatch): void;
+    /**
+     * @param elapsedTime - The elapsed time in milliseconds.
+     * @param date - The date when the {@link Stopwatch} was stopped.
+     * @param stopwatch - The {@link Stopwatch} instance.
+     */
+    (elapsedTime: number, date: Date, stopwatch: Stopwatch): void;
 }
 
-export default class Stopwatch {
-    #initialDate = 0;
-    #isRunning = false;
-    #elapsedMilliseconds = 0;
-    #onStart: StartCallback = null;
-    #onStop: StopCallback = null;
+/**
+ * A class for measuring elapsed time.
+ */
+export class Stopwatch {
+    /**
+     * Indicates whether the stopwatch is currently running.
+     */
+    private _isRunning: boolean;
 
-    public constructor(onStart?: StartCallback, onStop?: StopCallback) {
-        this.#onStart = onStart;
-        this.#onStop = onStop;
+    /**
+     * The time when stopwatch was started.
+     */
+    private _startTime: number;
+
+    /**
+     * The elapsed time in milliseconds since the stopwatch was started.
+     */
+    private _elapsedTime: number;
+
+    /**
+     * A callback function that will be called when the stopwatch is started.
+     */
+    private readonly _onStart?: StartCallback;
+
+    /**
+     * A callback function that will be called when the stopwatch is stopped.
+     */
+    private readonly _onStop?: StopCallback;
+
+    /**
+     * Creates a new instance of {@link Stopwatch}.
+     *
+     * @param onStart - A callback function that will be called when the stopwatch is started.
+     * @param onStop - A callback function that will be called when the stopwatch is stopped.
+     */
+    constructor(onStart?: StartCallback, onStop?: StopCallback) {
+        this._isRunning = false;
+        this._startTime = 0;
+        this._elapsedTime = 0;
+        this._onStart = onStart;
+        this._onStop = onStop;
     }
 
-    public get elapsedMilliseconds(): number {
-        return this.#isRunning
-            ? (this.#elapsedMilliseconds + new Date().valueOf() - this.#initialDate)
-            : this.#elapsedMilliseconds;
+    /**
+     * Gets the elapsed time in milliseconds since the stopwatch was started.
+     */
+    get elapsedMilliseconds(): number {
+        return this._elapsedTime + (this._isRunning ? Date.now() - this._startTime : 0);
     }
 
-    public get isRunning(): boolean {
-        return this.#isRunning;
+    /**
+     * Gets a value indicating whether the stopwatch is currently running.
+     */
+    get isRunning(): boolean {
+        return this._isRunning;
     }
 
-    public start(): boolean {
-        if (!this.#isRunning) {
-            const currentDate = new Date();
-            this.#initialDate = currentDate.valueOf();
-            this.#isRunning = true;
-            this.#onStart?.(currentDate, this);
-            return true;
+    /**
+     * Starts the stopwatch.
+     *
+     * @returns `true` if the stopwatch was successfully started; `false` if it was already running.
+     */
+    start(): boolean {
+        if (this._isRunning) {
+            return false;
         }
-        return false;
+
+        this._startTime = Date.now();
+        this._isRunning = true;
+        this._onStart?.(new Date(), this);
+        return true;
     }
 
-    public stop(): boolean {
-        if (this.#isRunning) {
-            const currentDate = new Date();
-            this.#elapsedMilliseconds += currentDate.valueOf() - this.#initialDate;
-            this.#isRunning = false;
-            this.#onStop?.(this.#elapsedMilliseconds, currentDate, this);
-            return true;
+    /**
+     * Stops the stopwatch.
+     *
+     * @returns `true` if the stopwatch was successfully stopped; `false` if it was already stopped.
+     */
+    stop(): boolean {
+        if (!this._isRunning) {
+            return false;
         }
-        return false;
+
+        this._elapsedTime += Date.now() - this._startTime;
+        this._isRunning = false;
+        this._onStop?.(this._elapsedTime, new Date(), this);
+        return true;
     }
 
-    public reset(): void {
+    /**
+     * Resets the stopwatch.
+     */
+    reset(): void {
         this.stop();
-        this.#elapsedMilliseconds = 0;
+        this._elapsedTime = 0;
     }
 
-    public restart(): void {
+    /**
+     * Restarts the stopwatch.
+     */
+    restart(): void {
         this.reset();
         this.start();
     }
 
-    public static startNew(onStart?: StartCallback, onStop?: StopCallback): Stopwatch {
+    /**
+     * Creates a new instance of {@link Stopwatch} and starts it.
+     *
+     * @param onStart - A callback function that will be called when the stopwatch is started.
+     * @param onStop - A callback function that will be called when the stopwatch is stopped.
+     *
+     * @returns The newly created and started stopwatch.
+     */
+    static startNew(onStart?: StartCallback, onStop?: StopCallback): Stopwatch {
         const stopwatch = new Stopwatch(onStart, onStop);
         stopwatch.start();
         return stopwatch;
diff --git a/tests/unit/utils/diagnostics/stopwatch.spec.ts b/tests/unit/utils/diagnostics/stopwatch.spec.ts
new file mode 100644
index 0000000..73f9612
--- /dev/null
+++ b/tests/unit/utils/diagnostics/stopwatch.spec.ts
@@ -0,0 +1,179 @@
+import { Stopwatch } from "@/utils/diagnostics/stopwatch";
+
+describe("Stopwatch", () => {
+    beforeEach(() => {
+        jest.useFakeTimers();
+        jest.setSystemTime(0);
+    });
+
+    afterEach(() => {
+        jest.useRealTimers();
+    });
+
+    describe("constructor", () => {
+        test("initializes with default values", () => {
+            const stopwatch = new Stopwatch();
+
+            expect(stopwatch.isRunning).toBe(false);
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+        });
+    });
+
+    describe("start", () => {
+        test("starts stopwatch", () => {
+            const onStart = jest.fn();
+            const onStop = jest.fn();
+            const stopwatch = new Stopwatch(onStart, onStop);
+
+            expect(stopwatch.start()).toBe(true);
+            expect(stopwatch.isRunning).toBe(true);
+            expect(onStart).toHaveBeenCalledTimes(1);
+            expect(onStart).toHaveBeenCalledWith(new Date(0), stopwatch);
+            expect(onStop).not.toHaveBeenCalled();
+        });
+
+        test("doesn't start if stopwatch is already running", () => {
+            const onStart = jest.fn();
+            const stopwatch = Stopwatch.startNew(onStart);
+
+            expect(stopwatch.start()).toBe(false);
+            expect(onStart).toHaveBeenCalledTimes(1);
+        });
+    });
+
+    describe("stop", () => {
+        test("stops stopwatch", () => {
+            const onStart = jest.fn();
+            const onStop = jest.fn();
+            const stopwatch = Stopwatch.startNew(onStart, onStop);
+
+            jest.advanceTimersByTime(1000);
+
+            expect(stopwatch.stop()).toBe(true);
+            expect(stopwatch.isRunning).toBe(false);
+            expect(onStart).toHaveBeenCalledTimes(1);
+            expect(onStart).toHaveBeenCalledWith(new Date(0), stopwatch);
+            expect(onStop).toHaveBeenCalledTimes(1);
+            expect(onStop).toHaveBeenCalledWith(1000, new Date(1000), stopwatch);
+        });
+
+        test("doesn't stop if stopwatch is already stopped", () => {
+            const onStop = jest.fn();
+            const stopwatch = new Stopwatch(undefined, onStop);
+
+            expect(stopwatch.stop()).toBe(false);
+            expect(onStop).not.toBeCalled();
+        });
+    });
+
+    describe("elapsedMilliseconds", () => {
+        test("measures elapsed time while stopwatch is running", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+
+            jest.advanceTimersByTime(1000);
+            expect(stopwatch.elapsedMilliseconds).toBe(1000);
+
+            jest.advanceTimersByTime(1000);
+            expect(stopwatch.elapsedMilliseconds).toBe(2000);
+        });
+
+        test("measures elapsed time correctly when stopwatch is stopped", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+
+            jest.advanceTimersByTime(1000);
+            expect(stopwatch.elapsedMilliseconds).toBe(1000);
+
+            jest.advanceTimersByTime(1000);
+            expect(stopwatch.elapsedMilliseconds).toBe(2000);
+
+            stopwatch.stop();
+            jest.advanceTimersByTime(1000);
+            expect(stopwatch.elapsedMilliseconds).toBe(2000);
+        });
+
+        test("returns 0 if the stopwatch was never started", () => {
+            const stopwatch = new Stopwatch();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+        });
+    });
+
+    describe("reset", () => {
+        test("resets stopwatch correctly while it's running", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            jest.advanceTimersByTime(1000);
+            stopwatch.reset();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(false);
+        });
+
+        test("resets stopwatch correctly when it's stopped", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            jest.advanceTimersByTime(1000);
+            stopwatch.stop();
+            stopwatch.reset();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(false);
+        });
+
+        test("does nothing if the stopwatch was never started", () => {
+            const stopwatch = new Stopwatch();
+            stopwatch.reset();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(false);
+        });
+    });
+
+    describe("restart", () => {
+        test("restarts stopwatch correctly while it's running", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            jest.advanceTimersByTime(1000);
+            stopwatch.restart();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(true);
+        });
+
+        test("restarts stopwatch correctly when it's stopped", () => {
+            const stopwatch = Stopwatch.startNew();
+
+            jest.advanceTimersByTime(1000);
+            stopwatch.stop();
+            stopwatch.restart();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(true);
+        });
+
+        test("starts the stopwatch if it was never started", () => {
+            const stopwatch = new Stopwatch();
+            stopwatch.restart();
+
+            expect(stopwatch.elapsedMilliseconds).toBe(0);
+            expect(stopwatch.isRunning).toBe(true);
+        });
+    });
+
+    describe("startNew", () => {
+        test("starts new stopwatch correctly", () => {
+            const onStart = jest.fn();
+            const onStop = jest.fn();
+            const stopwatch = Stopwatch.startNew(onStart, onStop);
+
+            expect(stopwatch.isRunning).toBe(true);
+            expect(onStart).toHaveBeenCalledTimes(1);
+            expect(onStart).toHaveBeenCalledWith(new Date(0), stopwatch);
+            expect(onStop).not.toHaveBeenCalled();
+        });
+    });
+});