diff --git a/src/ska_tango_base/base/task_queue_manager.py b/src/ska_tango_base/base/task_queue_manager.py
index ca4556bae426d15c4b74cd9d78c41f6827830d34..d5d5913ce5ab1efeb4bfda321e869928bcc9547b 100644
--- a/src/ska_tango_base/base/task_queue_manager.py
+++ b/src/ska_tango_base/base/task_queue_manager.py
@@ -167,7 +167,9 @@ import logging
 import threading
 import time
 import traceback
+from uuid import uuid4
 from queue import Empty, Queue
+from datetime import datetime
 from threading import Event
 from typing import Any, Callable, Dict, Optional, Tuple
 from dataclasses import dataclass
@@ -211,6 +213,31 @@ class TaskState(enum.IntEnum):
     """
 
 
+@dataclass
+class TaskUniqueId:
+    """Convenience class for the unique ID of a task."""
+
+    id_uuid: str
+    id_datetime: datetime
+    id_task_name: str
+
+    @classmethod
+    def generate_unique_id(cls, task_name: str) -> str:
+        """Return a new unique ID."""
+        return f"{uuid4()}_{time.time()}_{task_name}"
+
+    @classmethod
+    def from_unique_id(cls, unique_id: str):
+        """Parse a unique ID."""
+        parts = unique_id.split("_")
+        id_uuid = parts[0]
+        id_datetime = datetime.fromtimestamp(float(parts[1]))
+        id_task_name = "_".join(parts[2:])
+        return TaskUniqueId(
+            id_uuid=id_uuid, id_datetime=id_datetime, id_task_name=id_task_name
+        )
+
+
 @dataclass
 class TaskResult:
     """Convenience class for results."""
@@ -265,6 +292,10 @@ class TaskResult:
             unique_id=command_result[1],
         )
 
+    def get_task_unique_id(self) -> TaskUniqueId:
+        """Convert from the unique_id string to TaskUniqueId."""
+        return TaskUniqueId.from_unique_id(self.unique_id)
+
 
 class QueueTask:
     """A task that can be put on the queue."""
@@ -580,7 +611,7 @@ class QueueManager:
         :return: The unique ID of the command
         :rtype: string
         """
-        unique_id = self.get_unique_id(task.get_task_name())
+        unique_id = self.generate_unique_id(task.get_task_name())
 
         # Inject the events into the task
         task.kwargs["aborting_event"] = self.aborting_event
@@ -677,7 +708,7 @@ class QueueManager:
         return self.aborting_event.is_set()
 
     @classmethod
-    def get_unique_id(cls, task_name) -> str:
+    def generate_unique_id(cls, task_name) -> str:
         """Generate a unique ID for the task.
 
         :param task_name: The name of the task
@@ -685,7 +716,7 @@ class QueueManager:
         :return: The unique ID of the task
         :rtype: string
         """
-        return f"{time.time()}_{task_name}"
+        return TaskUniqueId.generate_unique_id(task_name)
 
     def get_task_state(self, unique_id: str) -> TaskState:
         """Attempt to get state of QueueTask.
diff --git a/tests/test_reference_base_device.py b/tests/test_reference_base_device.py
index 563d21f44d10450d4d04d4fdbb8a9cb29fc71096..cf62c30744c86e2929b5349e71be3e63962468b6 100644
--- a/tests/test_reference_base_device.py
+++ b/tests/test_reference_base_device.py
@@ -42,7 +42,7 @@ class TestCommands:
 
                 result = TaskResult.from_task_result(proxy.longRunningCommandResult)
                 assert result.result_code == ResultCode.OK
-                assert result.unique_id.endswith("SimpleTask")
+                assert result.get_task_unique_id().id_task_name == "SimpleTask"
 
     @pytest.mark.timeout(5)
     def test_non_aborting_command(self):
@@ -55,7 +55,7 @@ class TestCommands:
                     pass
                 result = TaskResult.from_task_result(proxy.longRunningCommandResult)
                 assert result.result_code == ResultCode.OK
-                assert result.unique_id.endswith("NonAbortingTask")
+                assert result.get_task_unique_id().id_task_name == "NonAbortingTask"
 
     @pytest.mark.timeout(5)
     def test_aborting_command(self):
@@ -155,7 +155,7 @@ def test_callbacks():
             # longRunningCommandResult
             assert len(attribute_values[10]) == 3
             tr = TaskResult.from_task_result(attribute_values[10])
-            tr.unique_id.endswith("ProgressTask")
+            assert tr.get_task_unique_id().id_task_name == "ProgressTask"
             tr.result_code == ResultCode.OK
             tr.task_result == "None"