diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index a55a0cae7bee5cf177294d65921684785632c844..e8622616c6245a924edacc4df2bc71a5a52c1254 100644
--- a/inc/ErrorHandler.hpp
+++ b/inc/ErrorHandler.hpp
@@ -52,7 +52,12 @@ public:
 			UnacceptablePacket = 5,
 
 		/**
-		 * Asked a Message type that it doesn't exist
+ 		 * A date that isn't valid according to the Gregorian calendar or cannot be parsed by the
+ 		 * TimeHelper
+ 		 */
+			InvalidDate = 6,
+		/**
+		 * Asked a Message type that doesn't exist
 		 */
 			UnknownMessageType = 6,
 	};
diff --git a/inc/Helpers/TimeHelper.hpp b/inc/Helpers/TimeHelper.hpp
index 8661fff4c05df60a8c43b583bec6a62695f060a7..711478568dcdd5ba64944852f6bbf0a6ae0ee233 100644
--- a/inc/Helpers/TimeHelper.hpp
+++ b/inc/Helpers/TimeHelper.hpp
@@ -4,38 +4,110 @@
 #include <cstdint>
 #include <Message.hpp>
 
+#define SECONDS_PER_MINUTE 60
+#define SECONDS_PER_HOUR 3600
+#define SECONDS_PER_DAY 86400
+
+/**
+ * The time and date provided from Real Time Clock (Real Time Clock).
+ *
+ * @notes
+ * This struct is similar to the `struct tm` of <ctime> library but it is more embedded-friendly
+ *
+ * For the current implementation this struct takes dummy values, because RTC hasn't been
+ * implemented
+ */
+struct TimeAndDate {
+	uint16_t year;
+	uint8_t month;
+	uint8_t day;
+	uint8_t hour;
+	uint8_t minute;
+	uint8_t second;
+};
+
 /**
  * This class formats the spacecraft time and cooperates closely with the ST[09] time management.
- * The ECSS standard supports two time formats: the CUC and CSD that are described in
- * CCSDS 301.0-B-4 standard
- * The chosen time format is CUC. The reasons for this selection are the followings:
- * 1)It is more flexible from the CSD. The designer is free to decide how much memory will use
- * for the time unit and what that time unit will be(seconds, minutes, hours etc.).
- * 2)It can use TAI(international atomic time) as reference time scale. So there is no need
- * to worry about leap seconds(code UTC-based)
  *
- * Note: The implementation of the time formats are in general RTC-dependent. First, we need to
- * get the time data from the RTC, so we know what time is it and then format it!
+ * The ECSS standard supports two time formats: the CUC and CSD that are described in CCSDS
+ * 301.0-B-4 standard. The chosen time format is CDS and it is UTC-based (UTC: Coordinated
+ * Universal Time). It consists of two main fields: the time code preamble field (P-field) and
+ * the time specification field (T-field). The P-Field is the metadata for the T-Field. The
+ * T-Field is consisted of two segments: 1) the `DAY` and the 2) `ms of day` segments.
+ * The P-field won't be included in the code, because as the ECSS standards claims, it can be
+ * just implicitly declared.
+ *
+ * @note
+ * Since this code is UTC-based, the leap second correction must be made. The leap seconds that
+ * have been occurred between timestamps should be considered if a critical time-difference is
+ * needed
+ *
  */
 class TimeHelper {
 public:
+	static constexpr uint8_t DaysOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+	TimeHelper() = default;
+
+	/**
+	 * @param year The year that will be examined if it is a leap year (366 days)
+	 * @return if the \p year is a leap year returns true and if it isn't returns false
+	 */
+	static bool IsLeapYear(uint16_t year);
+
+	/**
+     * Convert UTC date to elapsed seconds since Unix epoch (1/1/1970 00:00:00).
+     *
+     * This is a reimplemented mktime() of <ctime> library in an embedded systems way
+     *
+     * @note
+     * This function can convert UTC dates after 1 January 2019 to elapsed seconds since Unix epoch
+     *
+     * @param TimeInfo the time information/data from the RTC (UTC format)
+     * @return the elapsed seconds between a given UTC date (after the Unix epoch) and Unix epoch
+     * @todo check if we need to change the epoch to the recommended one from the standard, 1
+     * January 1958
+     */
+	static uint32_t utcToSeconds(struct TimeAndDate &TimeInfo);
+
+	/**
+     * Convert elapsed seconds since Unix epoch to UTC date.
+     *
+     * This is a reimplemented gmtime() of <ctime> library in an embedded systems way
+     *
+     * @note
+     * This function can convert elapsed seconds since Unix epoch to UTC dates after 1 January 2019
+     *
+     * @param seconds elapsed seconds since Unix epoch
+     * @return the UTC date based on the \p seconds
+     * @todo check if we need to change the epoch to the recommended one from the standard, 1
+     * January 1958
+     */
+	static struct TimeAndDate secondsToUTC(uint32_t seconds);
+
 	/**
-	 * Generate the CUC time format
+	 * Generate the CDS time format (3.3 in CCSDS 301.0-B-4 standard).
 	 *
-	 * @details The CUC time format consists of two main fields: the time code preamble field
-	 * (P-field) and the time specification field(T-field). The P-Field is the metadata for the
-	 * T-Field. The T-Field contains the value of the time unit and the designer decides what the
-	 * time unit will be, so this is a subject for discussion. The recommended time unit from the
-	 * standard is the second and it is probably the best solution for accuracy.
-	 * @param seconds the seconds provided from the RTC. This function in general should have
-	 * parameters corresponding with the RTC. For the time being we assume that the RTC has a
-	 * 32-bit counter that counts seconds(the RTC in Nucleo F103RB!)
- 	 * @todo check if we need milliseconds(fractions of the time unit)
- 	 * @todo the time unit should be declared in the metadata. But how?
- 	 * @todo check if we need to define other epoch than the 1 January 1958
+	 * Converts a UTC date to CDS time format.
+	 *
+	 * @param TimeInfo is the data provided from RTC (UTC)
+	 * @return TimeFormat the CDS time format. More specific, 48 bits are used for the T-field
+	 * (16 for the `DAY` and 32 for the `ms of day`)
  	 * @todo time security for critical time operations
+ 	 * @todo declare the implicit P-field
+ 	 * @todo check if we need milliseconds
+	 */
+	static uint64_t generateCDStimeFormat(struct TimeAndDate &TimeInfo);
+
+	/**
+	 * Parse the CDS time format (3.3 in CCSDS 301.0-B-4 standard)
+	 *
+     * @param data time information provided from the ground segment. The length of the data is a
+     * fixed size of 48 bits
+	 * @return the UTC date
 	 */
-	static uint64_t implementCUCTimeFormat(uint32_t seconds);
+	static struct TimeAndDate parseCDStimeFormat(const uint8_t *data);
 };
 
+
 #endif //ECSS_SERVICES_TIMEHELPER_HPP
diff --git a/inc/Services/TimeManagementService.hpp b/inc/Services/TimeManagementService.hpp
index d006a5d712b27ffc0218ef31dee469d5bb7d411a..533fcd5683f5dddd3258d00d8884c76a5da8b40c 100644
--- a/inc/Services/TimeManagementService.hpp
+++ b/inc/Services/TimeManagementService.hpp
@@ -1,20 +1,33 @@
 #ifndef ECSS_SERVICES_TIMEMANAGEMENTSERVICE_HPP
 #define ECSS_SERVICES_TIMEMANAGEMENTSERVICE_HPP
 
+
 #include <Service.hpp>
-#include <ctime>
 #include "Helpers/TimeHelper.hpp"
 
 /**
- * Implementation of the ST[09] time management. The current implementation sends
- * a report with the spacecraft time that is formatted according to the CUC time code format
- * (check TimeHelper for the format)
+ * Implementation of the ST[09] time management.
+ *
+ * @notes
+ * There is a noticeable difference between setting the time using GPS and setting the time
+ * using space packets from the ground segment. The GPS module sends the actual time of UTC (123519
+ * is 12:35:19 UTC), while space packets, for time configuration, sends the elapsed time units
+ * (seconds, days depends on the time format) from a specific epoch (1 January 1958 00:00:00). Time
+ * updates using GPS have nothing to do with this service, but for consistency and simplicity we
+ * are trying to set the time with a common way independently of the time source. This is also
+ * the reason that we chose CDS time format (because it is UTC based, check class `TimeHelper`)
+ *
+ * About the GPS receiver, we assume that it outputs NMEA (message format) data
  *
+ * @todo check if we need to follow the standard for time-management or we should send the time-data
+ * like GPS
+ * @todo check if the final GPS receiver support NMEA protocol
  * @todo When the time comes for the application processes we should consider this: All reports
  * generated by the application process that is identified by APID 0 are time reports
  * @todo Declare the time accuracy that the standard claims in the spacecraft
- * time reference section(6.9.3.d,e)
+ * time reference section (6.9.3.d,e)
  */
+
 class TimeManagementService : public Service {
 public:
 	TimeManagementService() {
@@ -22,15 +35,33 @@ public:
 	}
 
 	/**
-	 * TM[9,2] CUC time report
+	 * TM[9,3] CDS time report.
+	 *
+	 * This function sends reports with the spacecraft time that is formatted according to the CDS
+	 * time code format (check class `TimeHelper` for the format)
 	 *
+	 * @param TimeInfo the time information/data from the RTC (UTC format)
 	 * @todo check if we need spacecraft time reference status
 	 * @todo ECSS standard claims: <<The time reports generated by the time reporting subservice
 	 * are spacecraft time packets. A spacecraft time packet does not carry the message type,
 	 * consisting of the service type and message subtype.>> Check if we need to implement that
 	 * or should ignore the standard?
 	 */
-	void cucTimeReport();
+
+	void cdsTimeReport(struct TimeAndDate &TimeInfo);
+
+	/**
+	 * TC[9,128] CDS time request.
+	 *
+	 * This function is a custom subservice (mission specific) with message type 128 (as defined
+	 * from the standard for custom message types, 5.3.3.1.f) and it parses the data of the
+	 * time-management telecommand packet. This data is formatted according to the CDS time code
+	 * format (check class `TimeHelper` for the format)
+	 *
+	 * @param message the message that will be parsed for its time-data. The data of the \p message
+	 * should be a fixed size of 48 bits
+	 */
+	struct TimeAndDate cdsTimeRequest(Message &message);
 };
 
 
diff --git a/src/Helpers/TimeHelper.cpp b/src/Helpers/TimeHelper.cpp
index 462c7e8b35ea06bfe440f84b7e3e568e2a7891d2..2ce9562ba64ef73b854e365ae8dd3687944982fb 100644
--- a/src/Helpers/TimeHelper.cpp
+++ b/src/Helpers/TimeHelper.cpp
@@ -1,43 +1,136 @@
 #include "Helpers/TimeHelper.hpp"
 
-uint64_t TimeHelper::implementCUCTimeFormat(uint32_t seconds) {
-	// the total number of octets including the P-field (1 octet) and T-field(4 octets) is 5
-
-	// define the P-field
-	const uint8_t bit0 = 0; // P-field extension(‘zero’: no extension, ‘one’: field is extended)
-	const uint8_t bits1_3 = 1; // Time code identification ( 001 -> 1958 January 1 epoch )
-	const uint8_t bits4_5 = 4 - 1; // Number of octets of the basic time unit minus one
-	const uint8_t bits6_7 = 0; // Number of octets of the fractional time unit
-	const uint8_t pField = (bits6_7 << 6 | bits4_5 << 4 | bits1_3 << 1 | bit0);
-
-	// just a reminder to be careful with the assigned values
-	static_assert(bit0 < 2);
-	static_assert(bits1_3 < 16);
-	static_assert(bits4_5 < 4);
-	static_assert(bits6_7 < 4);
+bool TimeHelper::IsLeapYear(uint16_t year) {
+	if (year % 4 != 0) {
+		return false;
+	}
+	if (year % 100 != 0) {
+		return true;
+	}
+	return (year % 400) == 0;
+}
+
+uint32_t TimeHelper::utcToSeconds(struct TimeAndDate &TimeInfo) {
+	// the date, that \p TimeInfo represents, should be greater than or equal to 1/1/2019 and the
+	// date should be valid according to Gregorian calendar
+	assertI(TimeInfo.year >= 2019, ErrorHandler::InternalErrorType::InvalidDate);
+	assertI(1 <= TimeInfo.month && TimeInfo.month <= 12,
+	        ErrorHandler::InternalErrorType::InvalidDate);
+	assertI(1 <= TimeInfo.day && TimeInfo.day <= 31,
+	        ErrorHandler::InternalErrorType::InvalidDate);
+	assertI(0 <= TimeInfo.hour && TimeInfo.hour <= 24,
+	        ErrorHandler::InternalErrorType::InvalidDate);
+	assertI(0 <= TimeInfo.minute && TimeInfo.minute <= 60,
+	        ErrorHandler::InternalErrorType::InvalidDate);
+	assertI(0 <= TimeInfo.second && TimeInfo.second <= 60,
+	        ErrorHandler::InternalErrorType::InvalidDate);
+
+	uint32_t secs = 1546300800; // elapsed seconds from Unix epoch until 1/1/2019 00:00:00 (UTC)
+	for (uint16_t y = 2019; y < TimeInfo.year; ++y) {
+		secs += (IsLeapYear(y) ? 366 : 365) * SECONDS_PER_DAY;
+	}
+	for (uint16_t m = 1; m < TimeInfo.month; ++m) {
+		secs += DaysOfMonth[m - 1] * SECONDS_PER_DAY;
+		if (m == 2 && IsLeapYear(TimeInfo.year)) {
+			secs += SECONDS_PER_DAY;
+		}
+	}
+	secs += (TimeInfo.day - 1) * SECONDS_PER_DAY;
+	secs += TimeInfo.hour * SECONDS_PER_HOUR;
+	secs += TimeInfo.minute * SECONDS_PER_MINUTE;
+	secs += TimeInfo.second;
+	return secs;
+}
+
+struct TimeAndDate TimeHelper::secondsToUTC(uint32_t seconds) {
+	// elapsed seconds should be between dates, that are after 1/1/2019 and Unix epoch
+	assertI(seconds >= 1546300800, ErrorHandler::InternalErrorType::InvalidDate);
+
+	seconds -= 1546300800; // elapsed seconds from Unix epoch until 1/1/2019 00:00:00 (UTC)
+	struct TimeAndDate TimeInfo = {0};
+	TimeInfo.year = 2019;
+	TimeInfo.month = 1;
+	TimeInfo.day = 0;
+	TimeInfo.hour = 0;
+	TimeInfo.minute = 0;
+	TimeInfo.second = 0;
+
+	// calculate years
+	while (seconds >= (IsLeapYear(TimeInfo.year) ? 366 : 365) * SECONDS_PER_DAY) {
+		seconds -= (IsLeapYear(TimeInfo.year) ? 366 : 365) * SECONDS_PER_DAY;
+		TimeInfo.year++;
+	}
+
+	// calculate months
+	uint8_t i = 0;
+	while (seconds >= (DaysOfMonth[i] * SECONDS_PER_DAY)) {
+		TimeInfo.month++;
+		seconds -= (DaysOfMonth[i] * SECONDS_PER_DAY);
+		i++;
+		if (i == 1 && IsLeapYear(TimeInfo.year)) {
+			if (seconds <= (28 * SECONDS_PER_DAY)) {
+				break;
+			}
+			TimeInfo.month++;
+			seconds -= 29 * SECONDS_PER_DAY;
+			i++;
+		}
+	}
+
+	// calculate days
+	TimeInfo.day = seconds / SECONDS_PER_DAY;
+	seconds -= TimeInfo.day * SECONDS_PER_DAY;
+	TimeInfo.day++; // add 1 day because we start count from 1 January (and not 0 January!)
+
+	// calculate hours
+	TimeInfo.hour = seconds / SECONDS_PER_HOUR;
+	seconds -= TimeInfo.hour * SECONDS_PER_HOUR;
+
+	// calculate minutes
+	TimeInfo.minute = seconds / SECONDS_PER_MINUTE;
+	seconds -= TimeInfo.minute * SECONDS_PER_MINUTE;
+
+	// calculate seconds
+	TimeInfo.second = seconds;
+
+	return TimeInfo;
+}
+
+uint64_t TimeHelper::generateCDStimeFormat(struct TimeAndDate &TimeInfo) {
+	/**
+	 * Define the T-field. The total number of octets for the implementation of T-field is 6 (2 for
+	 * the `DAY` and 4 for the `ms of day`
+	 */
+
+
+	uint32_t seconds = utcToSeconds(TimeInfo);
 
 	/**
-	 * Define the T-field, the seconds passed from the defined epoch 1 January 1958
-	 * We use 4 octets(32 bits) for the time unit(seconds) because 32 bits for the seconds are
-	 * enough to count 136 years! But if we use 24 bits for the seconds then it will count 0,5
-	 * years and this isn't enough. Remember we can use only integers numbers of octets for the
-	 * time unit(second)
-	 *
-	 * @todo the implementation of the total seconds depends on the structure of the RTC
+	 * The `DAY` segment, 16 bits as defined from standard. Actually the days passed since Unix
+	 * epoch
 	 */
-	uint32_t totalSeconds = seconds;
+	auto elapsedDays = static_cast<uint16_t>(seconds / SECONDS_PER_DAY);
 
 	/**
-	 * Define time format including P-field and T-Field
-	 *
-	 * Notes:
-	 * Only the 40 bits of the 64 will be used for the timeFormat(0-7 : P-field, 8-39: T-field)
-	 *
-	 * Shift operators have high priority. That's why we should do a type-casting first so we
-	 * don't lose valuable bits
-	*/
-	uint64_t timeFormat = (static_cast<uint64_t>(totalSeconds) << 8 | pField);
+	 * The `ms of day` segment, 32 bits as defined in standard. The `ms of the day` and DAY`
+	 * should give the time passed since Unix epoch
+	 */
+	auto msOfDay = static_cast<uint32_t >((seconds % SECONDS_PER_DAY) * 1000);
 
+	uint64_t timeFormat = (static_cast<uint64_t>(elapsedDays) << 32 | msOfDay);
 
 	return timeFormat;
 }
+
+struct TimeAndDate TimeHelper::parseCDStimeFormat(const uint8_t *data) {
+	uint16_t elapsedDays = (static_cast<uint16_t >(data[0])) << 8 | static_cast<uint16_t >
+	(data[1]);
+	uint32_t msOfDay = (static_cast<uint32_t >(data[2])) << 24 |
+	                   (static_cast<uint32_t >(data[3])) << 16 |
+	                   (static_cast<uint32_t >(data[4])) << 8 |
+	                   static_cast<uint32_t >(data[5]);
+
+	uint32_t seconds = elapsedDays * SECONDS_PER_DAY + msOfDay / 1000;
+
+	return secondsToUTC(seconds);
+}
diff --git a/src/Services/TimeManagementService.cpp b/src/Services/TimeManagementService.cpp
index 2b3feb68aa059b7131863d84cd2d6e79d8328fa1..ad4d8c9208fb2fa558487c4fcf1868633f37a379 100644
--- a/src/Services/TimeManagementService.cpp
+++ b/src/Services/TimeManagementService.cpp
@@ -1,20 +1,26 @@
 #include "Services/TimeManagementService.hpp"
 
-void TimeManagementService::cucTimeReport() {
-	// TM[9,2] CUC time report
+void TimeManagementService::cdsTimeReport(struct TimeAndDate &TimeInfo) {
+	// TM[9,3] CDS time report
 
-	Message timeReport = createTM(2);
+	Message timeReport = createTM(3);
 
-	/**
-	 * For the time being we will use C++ functions to get a time value, but this will change
-	 * when the RTC will be implemented
-	 */
-	uint32_t seconds;
-	seconds = time(nullptr); // seconds have passed since 00:00:00 GMT, Jan 1, 1970
-	uint64_t timeFormat = TimeHelper::implementCUCTimeFormat(seconds); // store the return value
+	uint64_t timeFormat = TimeHelper::generateCDStimeFormat(TimeInfo);
 
-	timeReport.appendByte(timeFormat); // append the P-field
-	timeReport.appendWord(timeFormat >> 8); // append the T-field
+	timeReport.appendHalfword(static_cast<uint16_t >(timeFormat >> 32));
+	timeReport.appendWord(static_cast<uint32_t >(timeFormat));
 
 	storeMessage(timeReport);
 }
+
+struct TimeAndDate TimeManagementService::cdsTimeRequest(Message &message) {
+	// TC[9,128] CDS time request
+
+	// check if we have the correct size of the data. The size should be 6 (48 bits)
+	ErrorHandler::assertRequest(message.dataSize == 6, message,
+	                            ErrorHandler::AcceptanceErrorType::UnacceptableMessage);
+
+	struct TimeAndDate timeInfo = TimeHelper::parseCDStimeFormat(message.data);
+
+	return timeInfo;
+}
diff --git a/src/main.cpp b/src/main.cpp
index 71cff47e6621395665b6f1b163b20b053238c2e0..bdf4914e8cd7903523843bc515b33309e0cccdf2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -197,14 +197,17 @@ int main() {
 	errorMessage.appendBits(2, 7);
 	errorMessage.appendByte(15);
 
-
-	// TimeHelper test
-	uint64_t test = TimeHelper::implementCUCTimeFormat(1200);
-	std::cout << "\n" << test << "\n";
-
 	// ST[09] test
-	TimeManagementService & timeReport = Services.timeManagement;
-	timeReport.cucTimeReport();
+    TimeManagementService & timeReport = Services.timeManagement;
+	struct TimeAndDate timeInfo = {0};
+	// 10/04/1998 10:15:00
+	timeInfo.year = 1998;
+	timeInfo.month = 4;
+	timeInfo.day = 10;
+	timeInfo.hour = 10;
+	timeInfo.minute = 15;
+	timeInfo.second = 0;
+	timeReport.cdsTimeReport(timeInfo);
 
 	// ST[05] (5,5 to 5,8) test [works]
 	EventReportService::Event eventIDs[] = {EventReportService::HighSeverityUnknownEvent,
diff --git a/test/Helpers/TimeHelper.cpp b/test/Helpers/TimeHelper.cpp
index 0b23a2a05d7bb06a032bbfee1c51f2baa6d2f23d..c0c530d55a4e8704e0c833001769c0c28ac67ba3 100644
--- a/test/Helpers/TimeHelper.cpp
+++ b/test/Helpers/TimeHelper.cpp
@@ -2,9 +2,232 @@
 #include "Helpers/TimeHelper.hpp"
 
 TEST_CASE("Time format implementation", "[CUC]") {
-	// very simple tests for the TimeHelper
 
-	CHECK(TimeHelper::implementCUCTimeFormat(60) == 0b11110000110010);
-	CHECK(TimeHelper::implementCUCTimeFormat(1000) == 0x3E832);
-	CHECK(TimeHelper::implementCUCTimeFormat(1200) == 0x4B032);
+	SECTION("Invalid date") {
+		struct TimeAndDate TimeInfo = {0};
+
+		// invalid year
+		TimeInfo.year = 2018;
+		TimeInfo.month = 4;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 0;
+
+		TimeHelper time;
+		TimeHelper::utcToSeconds(TimeInfo);
+
+		// invalid month
+		TimeInfo.year = 2018;
+		TimeInfo.month = 60;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 0;
+
+		TimeHelper::utcToSeconds(TimeInfo);
+
+		// invalid day
+		TimeInfo.year = 2018;
+		TimeInfo.month = 4;
+		TimeInfo.day = 35;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 0;
+
+		TimeHelper::utcToSeconds(TimeInfo);
+
+		// invalid hour
+		TimeInfo.year = 2018;
+		TimeInfo.month = 4;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 100;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 0;
+
+		TimeHelper::utcToSeconds(TimeInfo);
+
+		// invalid minute
+		TimeInfo.year = 2018;
+		TimeInfo.month = 4;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 200;
+		TimeInfo.second = 0;
+
+		TimeHelper::utcToSeconds(TimeInfo);
+
+		// invalid second
+		TimeInfo.year = 2018;
+		TimeInfo.month = 4;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 122;
+
+		TimeHelper::utcToSeconds(TimeInfo);
+	}
+
+	SECTION("Convert UTC date to elapsed seconds since Unix epoch") {
+		struct TimeAndDate TimeInfo = {0};
+		// 10/04/2020 10:15:00
+		TimeInfo.year = 2020;
+		TimeInfo.month = 4;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 10;
+		TimeInfo.minute = 15;
+		TimeInfo.second = 0;
+
+		TimeHelper time;
+		uint32_t currTime = TimeHelper::utcToSeconds(TimeInfo);
+
+		uint16_t elapsedDays = currTime / 86400;
+		uint32_t msOfDay = currTime % 86400 * 1000;
+		uint64_t timeFormat = (static_cast<uint64_t>(elapsedDays) << 32 | msOfDay);
+		CHECK(TimeHelper::generateCDStimeFormat(TimeInfo) == timeFormat);
+
+		// 1/1/2019 00:00:00
+		TimeInfo.year = 2019;
+		TimeInfo.month = 1;
+		TimeInfo.day = 1;
+		TimeInfo.hour = 0;
+		TimeInfo.minute = 0;
+		TimeInfo.second = 0;
+
+		currTime = TimeHelper::utcToSeconds(TimeInfo);
+
+		elapsedDays = currTime / 86400;
+		msOfDay = currTime % 86400 * 1000;
+		timeFormat = (static_cast<uint64_t>(elapsedDays) << 32 | msOfDay);
+		CHECK(TimeHelper::generateCDStimeFormat(TimeInfo) == timeFormat);
+
+		// 5/12/2020 00:00:00
+		TimeInfo.year = 2020;
+		TimeInfo.month = 12;
+		TimeInfo.day = 5;
+		TimeInfo.hour = 0;
+		TimeInfo.minute = 0;
+		TimeInfo.second = 0;
+
+		currTime = TimeHelper::utcToSeconds(TimeInfo);
+		CHECK(currTime == 1607126400);
+
+		// 10/12/2020 00:00:00
+		TimeInfo.year = 2020;
+		TimeInfo.month = 12;
+		TimeInfo.day = 10;
+		TimeInfo.hour = 0;
+		TimeInfo.minute = 0;
+		TimeInfo.second = 0;
+
+		currTime = TimeHelper::utcToSeconds(TimeInfo);
+		CHECK(currTime == 1607558400);
+
+		// 15/12/2020 00:00:00
+		TimeInfo.year = 2020;
+		TimeInfo.month = 12;
+		TimeInfo.day = 15;
+		TimeInfo.hour = 0;
+		TimeInfo.minute = 0;
+		TimeInfo.second = 0;
+
+		currTime = TimeHelper::utcToSeconds(TimeInfo);
+		CHECK(currTime == 1607990400);
+
+		// 20/12/2020 00:00:00
+		TimeInfo.year = 2020;
+		TimeInfo.month = 12;
+		TimeInfo.day = 20;
+		TimeInfo.hour = 0;
+		TimeInfo.minute = 0;
+		TimeInfo.second = 0;
+
+		currTime = TimeHelper::utcToSeconds(TimeInfo);
+		CHECK(currTime == 1608422400);
+	}
+
+	SECTION("Convert elapsed seconds since Unix epoch to UTC date"){
+		uint32_t seconds = 1586513700; // elapsed seconds between 10/04/2020 10:15:00 and Unix epoch
+
+		TimeHelper time;
+		struct TimeAndDate TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2020);
+		CHECK(TimeInfo.month == 4);
+		CHECK(TimeInfo.day == 10);
+		CHECK(TimeInfo.hour == 10);
+		CHECK(TimeInfo.minute == 15);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1546300800; // elapsed seconds between 1/1/2019 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2019);
+		CHECK(TimeInfo.month == 1);
+		CHECK(TimeInfo.day == 1);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1550966400; // elapsed seconds between 24/2/2019 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2019);
+		CHECK(TimeInfo.month == 2);
+		CHECK(TimeInfo.day == 24);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1551571200; // elapsed seconds between 3/3/2019 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2019);
+		CHECK(TimeInfo.month == 3);
+		CHECK(TimeInfo.day == 3);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1742907370; // elapsed seconds between 25/3/2025 12:56:10 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2025);
+		CHECK(TimeInfo.month == 3);
+		CHECK(TimeInfo.day == 25);
+		CHECK(TimeInfo.hour == 12);
+		CHECK(TimeInfo.minute == 56);
+		CHECK(TimeInfo.second == 10);
+
+		seconds = 1583020800; // elapsed seconds between 1/3/2020 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2020);
+		CHECK(TimeInfo.month == 3);
+		CHECK(TimeInfo.day == 1);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1582934400; // elapsed seconds between 2/29/2020 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2020);
+		CHECK(TimeInfo.month == 2);
+		CHECK(TimeInfo.day == 29);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+		seconds = 1577923200; // elapsed seconds between 2/1/2020 00:00:00 and Unix epoch
+
+		TimeInfo = TimeHelper::secondsToUTC(seconds);
+		CHECK(TimeInfo.year == 2020);
+		CHECK(TimeInfo.month == 1);
+		CHECK(TimeInfo.day == 2);
+		CHECK(TimeInfo.hour == 0);
+		CHECK(TimeInfo.minute == 0);
+		CHECK(TimeInfo.second == 0);
+
+	}
+
 }
diff --git a/test/Services/TimeManagementService.cpp b/test/Services/TimeManagementService.cpp
index f9ca595348edeae12b818c716a36a29ec8d68ddb..9a4894f6ba09d939fe42dee17b68f0d19cd84461 100644
--- a/test/Services/TimeManagementService.cpp
+++ b/test/Services/TimeManagementService.cpp
@@ -2,15 +2,76 @@
 #include <Services/TimeManagementService.hpp>
 #include "ServiceTests.hpp"
 
-TimeManagementService & timeFormat = Services.timeManagement;
+TimeManagementService & timeService = Services.timeManagement;
 
-TEST_CASE("TM[9,2]", "[service][st09]") {
-	uint32_t seconds;
-	seconds = time(nullptr);
+TEST_CASE("TM[9,3]", "[service][st09]") {
+	struct TimeAndDate TimeInfo = {0};
+	// 10/04/2020 10:15:00
+	TimeInfo.year = 2020;
+	TimeInfo.month = 4;
+	TimeInfo.day = 10;
+	TimeInfo.hour = 10;
+	TimeInfo.minute = 15;
+	TimeInfo.second = 0;
 
-	timeFormat.cucTimeReport();
+	uint32_t currTime = TimeHelper::utcToSeconds(TimeInfo);
+
+	uint16_t elapsedDays = currTime/86400;
+	uint32_t msOfDay = currTime % 86400 * 1000;
+	uint64_t timeFormat = (static_cast<uint64_t>(elapsedDays) << 32 | msOfDay);
+
+	timeService.cdsTimeReport(TimeInfo);
 	Message response = ServiceTests::get(0);
-	CHECK(response.readByte() == 50);
-	CHECK(response.readWord() == seconds);
+	CHECK(response.serviceType == 9);
+	CHECK(response.messageType == 3);
+	CHECK(response.packetType == Message::TM);
+	CHECK(response.readHalfword() == static_cast<uint16_t>(timeFormat >> 32));
+	CHECK(response.readWord() == static_cast<uint32_t >(timeFormat));
+
+	Message message = Message(9, 128, Message::TC, 3);
+	message.appendHalfword(static_cast<uint16_t >(timeFormat >> 32));
+	message.appendWord(static_cast<uint32_t >(timeFormat));
+
+	TimeInfo = timeService.cdsTimeRequest(message);
+	CHECK(TimeInfo.year == 2020);
+	CHECK(TimeInfo.month == 4);
+	CHECK(TimeInfo.day == 10);
+	CHECK(TimeInfo.hour == 10);
+	CHECK(TimeInfo.minute == 15);
+	CHECK(TimeInfo.second == 0);
+
+
+	// 1/1/2019 00:00:00
+	TimeInfo.year = 2019;
+	TimeInfo.month = 1;
+	TimeInfo.day = 1;
+	TimeInfo.hour = 0;
+	TimeInfo.minute = 0;
+	TimeInfo.second = 0;
+
+	currTime = TimeHelper::utcToSeconds(TimeInfo);
+
+	elapsedDays = currTime/86400;
+	msOfDay = currTime % 86400 * 1000;
+	timeFormat = (static_cast<uint64_t>(elapsedDays) << 32 | msOfDay);
+
+	timeService.cdsTimeReport(TimeInfo);
+	response = ServiceTests::get(1);
+	CHECK(response.serviceType == 9);
+	CHECK(response.messageType == 3);
+	CHECK(response.packetType == Message::TM);
+	CHECK(response.readHalfword() == static_cast<uint16_t>(timeFormat >> 32));
+	CHECK(response.readWord() == static_cast<uint32_t >(timeFormat));
+
+	message = Message(9, 128, Message::TC, 3);
+	message.appendHalfword(static_cast<uint16_t >(timeFormat >> 32));
+	message.appendWord(static_cast<uint32_t >(timeFormat));
 
+	TimeInfo = timeService.cdsTimeRequest(message);
+	CHECK(TimeInfo.year == 2019);
+	CHECK(TimeInfo.month == 1);
+	CHECK(TimeInfo.day == 1);
+	CHECK(TimeInfo.hour == 0);
+	CHECK(TimeInfo.minute == 0);
+	CHECK(TimeInfo.second == 0);
 }