Move time utils to be in one place
We've accumulated several time utility functions in the http classes.
Time isn't a core HTTP primitive, so http is not where those functions
below.
This commit moves all the time functions from the crow::utility
namespace into the redfish::time_utils namespace, as well as moves the
unit tests.
No code changes where made to the individual functions, with the
exception of changing the namespace on the unit tests.
Tested: Unit tests pass.
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I8493375f60aea31899c84ae703e0f71a17dbdb73
diff --git a/http/ut/utility_test.cpp b/http/ut/utility_test.cpp
index 8bc122f..4d9bd91 100644
--- a/http/ut/utility_test.cpp
+++ b/http/ut/utility_test.cpp
@@ -81,63 +81,6 @@
EXPECT_EQ(data, decoded);
}
-TEST(Utility, GetDateTimeStdtime)
-{
- // some time before the epoch
- EXPECT_EQ(getDateTimeStdtime(std::time_t{-1234567}),
- "1970-01-01T00:00:00+00:00");
-
- // epoch
- EXPECT_EQ(getDateTimeStdtime(std::time_t{0}), "1970-01-01T00:00:00+00:00");
-
- // Limits
- EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::max()),
- "9999-12-31T23:59:59+00:00");
- EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::min()),
- "1970-01-01T00:00:00+00:00");
-}
-
-TEST(Utility, GetDateTimeUint)
-{
- EXPECT_EQ(getDateTimeUint(uint64_t{1638312095}),
- "2021-11-30T22:41:35+00:00");
- // some time in the future, beyond 2038
- EXPECT_EQ(getDateTimeUint(uint64_t{41638312095}),
- "3289-06-18T21:48:15+00:00");
- // the maximum time we support
- EXPECT_EQ(getDateTimeUint(uint64_t{253402300799}),
- "9999-12-31T23:59:59+00:00");
-
- // returns the maximum Redfish date
- EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::max()),
- "9999-12-31T23:59:59+00:00");
-
- EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::min()),
- "1970-01-01T00:00:00+00:00");
-}
-
-TEST(Utility, GetDateTimeUintMs)
-{
- EXPECT_EQ(getDateTimeUintMs(uint64_t{1638312095123}),
- "2021-11-30T22:41:35.123+00:00");
- // returns the maximum Redfish date
- EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::max()),
- "9999-12-31T23:59:59.999+00:00");
- EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::min()),
- "1970-01-01T00:00:00.000+00:00");
-}
-
-TEST(Utility, GetDateTimeUintUs)
-{
- EXPECT_EQ(getDateTimeUintUs(uint64_t{1638312095123456}),
- "2021-11-30T22:41:35.123456+00:00");
- // returns the maximum Redfish date
- EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::max()),
- "9999-12-31T23:59:59.999999+00:00");
- EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::min()),
- "1970-01-01T00:00:00.000000+00:00");
-}
-
TEST(Utility, UrlFromPieces)
{
boost::urls::url url = urlFromPieces("redfish", "v1", "foo");
diff --git a/http/utility.hpp b/http/utility.hpp
index c9728f5..e08e565 100644
--- a/http/utility.hpp
+++ b/http/utility.hpp
@@ -539,190 +539,6 @@
return true;
}
-namespace details
-{
-// Returns year/month/day triple in civil calendar
-// Preconditions: z is number of days since 1970-01-01 and is in the range:
-// [numeric_limits<Int>::min(),
-// numeric_limits<Int>::max()-719468].
-// Algorithm sourced from
-// https://howardhinnant.github.io/date_algorithms.html#civil_from_days
-// All constants are explained in the above
-template <class IntType>
-constexpr std::tuple<IntType, unsigned, unsigned>
- civilFromDays(IntType z) noexcept
-{
- z += 719468;
- IntType era = (z >= 0 ? z : z - 146096) / 146097;
- unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
- unsigned yoe =
- (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399]
- IntType y = static_cast<IntType>(yoe) + era * 400;
- unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365]
- unsigned mp = (5 * doy + 2) / 153; // [0, 11]
- unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31]
- unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12]
-
- return std::tuple<IntType, unsigned, unsigned>(y + (m <= 2), m, d);
-}
-
-// Creates a string from an integer in the most efficient way possible without
-// using std::locale. Adds an exact zero pad based on the pad input parameter.
-// Does not handle negative numbers.
-inline std::string padZeros(int value, size_t pad)
-{
- std::string result(pad, '0');
- for (int val = value; pad > 0; pad--)
- {
- result[pad - 1] = static_cast<char>('0' + val % 10);
- val /= 10;
- }
- return result;
-}
-
-template <typename IntType, typename Period>
-std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
-{
- using seconds = std::chrono::duration<int>;
- using minutes = std::chrono::duration<int, std::ratio<60>>;
- using hours = std::chrono::duration<int, std::ratio<3600>>;
- using days = std::chrono::duration<
- IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
-
- // d is days since 1970-01-01
- days d = std::chrono::duration_cast<days>(t);
-
- // t is now time duration since midnight of day d
- t -= d;
-
- // break d down into year/month/day
- int year = 0;
- int month = 0;
- int day = 0;
- std::tie(year, month, day) = details::civilFromDays(d.count());
- // Check against limits. Can't go above year 9999, and can't go below epoch
- // (1970)
- if (year >= 10000)
- {
- year = 9999;
- month = 12;
- day = 31;
- t = days(1) - std::chrono::duration<IntType, Period>(1);
- }
- else if (year < 1970)
- {
- year = 1970;
- month = 1;
- day = 1;
- t = std::chrono::duration<IntType, Period>::zero();
- }
- std::string out;
- out += details::padZeros(year, 4);
- out += '-';
- out += details::padZeros(month, 2);
- out += '-';
- out += details::padZeros(day, 2);
-
- out += 'T';
- hours hr = duration_cast<hours>(t);
- out += details::padZeros(hr.count(), 2);
- t -= hr;
- out += ':';
-
- minutes mt = duration_cast<minutes>(t);
- out += details::padZeros(mt.count(), 2);
- t -= mt;
- out += ':';
-
- seconds se = duration_cast<seconds>(t);
- out += details::padZeros(se.count(), 2);
- t -= se;
-
- if constexpr (std::is_same_v<typename decltype(t)::period, std::milli>)
- {
- out += '.';
- using MilliDuration = std::chrono::duration<int, std::milli>;
- MilliDuration subsec = duration_cast<MilliDuration>(t);
- out += details::padZeros(subsec.count(), 3);
- }
- else if constexpr (std::is_same_v<typename decltype(t)::period, std::micro>)
- {
- out += '.';
- using MicroDuration = std::chrono::duration<int, std::micro>;
- MicroDuration subsec = duration_cast<MicroDuration>(t);
- out += details::padZeros(subsec.count(), 6);
- }
-
- out += "+00:00";
- return out;
-}
-} // namespace details
-
-// Returns the formatted date time string.
-// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
-// the given |secondsSinceEpoch| is too large, we return the maximum supported
-// date.
-inline std::string getDateTimeUint(uint64_t secondsSinceEpoch)
-{
- using DurationType = std::chrono::duration<uint64_t>;
- DurationType sinceEpoch(secondsSinceEpoch);
- return details::toISO8061ExtendedStr(sinceEpoch);
-}
-
-// Returns the formatted date time string with millisecond precision
-// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
-// the given |secondsSinceEpoch| is too large, we return the maximum supported
-// date.
-inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch)
-{
- using DurationType = std::chrono::duration<uint64_t, std::milli>;
- DurationType sinceEpoch(milliSecondsSinceEpoch);
- return details::toISO8061ExtendedStr(sinceEpoch);
-}
-
-// Returns the formatted date time string with microsecond precision
-inline std::string getDateTimeUintUs(uint64_t microSecondsSinceEpoch)
-{
- using DurationType = std::chrono::duration<uint64_t, std::micro>;
- DurationType sinceEpoch(microSecondsSinceEpoch);
- return details::toISO8061ExtendedStr(sinceEpoch);
-}
-
-inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch)
-{
- using DurationType = std::chrono::duration<std::time_t>;
- DurationType sinceEpoch(secondsSinceEpoch);
- return details::toISO8061ExtendedStr(sinceEpoch);
-}
-
-/**
- * Returns the current Date, Time & the local Time Offset
- * infromation in a pair
- *
- * @param[in] None
- *
- * @return std::pair<std::string, std::string>, which consist
- * of current DateTime & the TimeOffset strings respectively.
- */
-inline std::pair<std::string, std::string> getDateTimeOffsetNow()
-{
- std::time_t time = std::time(nullptr);
- std::string dateTime = getDateTimeStdtime(time);
-
- /* extract the local Time Offset value from the
- * recevied dateTime string.
- */
- std::string timeOffset("Z00:00");
- std::size_t lastPos = dateTime.size();
- std::size_t len = timeOffset.size();
- if (lastPos > len)
- {
- timeOffset = dateTime.substr(lastPos - len);
- }
-
- return std::make_pair(dateTime, timeOffset);
-}
-
inline bool constantTimeStringCompare(const std::string_view a,
const std::string_view b)
{
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index d581aeb..2087e54 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -416,15 +416,15 @@
logEntryArray.push_back({});
nlohmann::json& logEntryJson = logEntryArray.back();
- logEntryJson = {
- {"EventId", "TestID"},
- {"EventType", "Event"},
- {"Severity", "OK"},
- {"Message", "Generated test event"},
- {"MessageId", "OpenBMC.0.2.TestEventLog"},
- {"MessageArgs", nlohmann::json::array()},
- {"EventTimestamp", crow::utility::getDateTimeOffsetNow().first},
- {"Context", customText}};
+ logEntryJson = {{"EventId", "TestID"},
+ {"EventType", "Event"},
+ {"Severity", "OK"},
+ {"Message", "Generated test event"},
+ {"MessageId", "OpenBMC.0.2.TestEventLog"},
+ {"MessageArgs", nlohmann::json::array()},
+ {"EventTimestamp",
+ redfish::time_utils::getDateTimeOffsetNow().first},
+ {"Context", customText}};
nlohmann::json msg;
msg["@odata.type"] = "#Event.v1_4_0.Event";
@@ -1027,7 +1027,8 @@
nlohmann::json event = {
{"EventId", eventId},
{"MemberId", memberId},
- {"EventTimestamp", crow::utility::getDateTimeOffsetNow().first},
+ {"EventTimestamp",
+ redfish::time_utils::getDateTimeOffsetNow().first},
{"OriginOfCondition", origin}};
for (nlohmann::json::iterator it = event.begin(); it != event.end();
++it)
@@ -1085,7 +1086,8 @@
{
std::shared_ptr<Subscription> entry = it.second;
nlohmann::json msgJson = {
- {"Timestamp", crow::utility::getDateTimeOffsetNow().first},
+ {"Timestamp",
+ redfish::time_utils::getDateTimeOffsetNow().first},
{"OriginOfCondition", "/ibm/v1/HMC/BroadcastService"},
{"Name", "Broadcast Message"},
{"Message", broadcastMsg}};
diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
index e814c51..2733ba2 100644
--- a/redfish-core/include/utils/time_utils.hpp
+++ b/redfish-core/include/utils/time_utils.hpp
@@ -238,5 +238,190 @@
return std::make_optional(duration);
}
+namespace details
+{
+// Returns year/month/day triple in civil calendar
+// Preconditions: z is number of days since 1970-01-01 and is in the range:
+// [numeric_limits<Int>::min(),
+// numeric_limits<Int>::max()-719468].
+// Algorithm sourced from
+// https://howardhinnant.github.io/date_algorithms.html#civil_from_days
+// All constants are explained in the above
+template <class IntType>
+constexpr std::tuple<IntType, unsigned, unsigned>
+ civilFromDays(IntType z) noexcept
+{
+ z += 719468;
+ IntType era = (z >= 0 ? z : z - 146096) / 146097;
+ unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
+ unsigned yoe =
+ (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399]
+ IntType y = static_cast<IntType>(yoe) + era * 400;
+ unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365]
+ unsigned mp = (5 * doy + 2) / 153; // [0, 11]
+ unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31]
+ unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12]
+
+ return std::tuple<IntType, unsigned, unsigned>(y + (m <= 2), m, d);
+}
+
+// Creates a string from an integer in the most efficient way possible without
+// using std::locale. Adds an exact zero pad based on the pad input parameter.
+// Does nt handle negative numbers.
+inline std::string padZeros(int value, size_t pad)
+{
+ std::string result(pad, '0');
+ for (int val = value; pad > 0; pad--)
+ {
+ result[pad - 1] = static_cast<char>('0' + val % 10);
+ val /= 10;
+ }
+ return result;
+}
+
+template <typename IntType, typename Period>
+std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
+{
+ using seconds = std::chrono::duration<int>;
+ using minutes = std::chrono::duration<int, std::ratio<60>>;
+ using hours = std::chrono::duration<int, std::ratio<3600>>;
+ using days = std::chrono::duration<
+ IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
+
+ // d is days since 1970-01-01
+ days d = std::chrono::duration_cast<days>(t);
+
+ // t is now time duration since midnight of day d
+ t -= d;
+
+ // break d down into year/month/day
+ int year = 0;
+ int month = 0;
+ int day = 0;
+ std::tie(year, month, day) = details::civilFromDays(d.count());
+ // Check against limits. Can't go above year 9999, and can't go below epoch
+ // (1970)
+ if (year >= 10000)
+ {
+ year = 9999;
+ month = 12;
+ day = 31;
+ t = days(1) - std::chrono::duration<IntType, Period>(1);
+ }
+ else if (year < 1970)
+ {
+ year = 1970;
+ month = 1;
+ day = 1;
+ t = std::chrono::duration<IntType, Period>::zero();
+ }
+
+ std::string out;
+ out += details::padZeros(year, 4);
+ out += '-';
+ out += details::padZeros(month, 2);
+ out += '-';
+ out += details::padZeros(day, 2);
+ out += 'T';
+ hours hr = duration_cast<hours>(t);
+ out += details::padZeros(hr.count(), 2);
+ t -= hr;
+ out += ':';
+
+ minutes mt = duration_cast<minutes>(t);
+ out += details::padZeros(mt.count(), 2);
+ t -= mt;
+ out += ':';
+
+ seconds se = duration_cast<seconds>(t);
+ out += details::padZeros(se.count(), 2);
+ t -= se;
+
+ if constexpr (std::is_same_v<typename decltype(t)::period, std::milli>)
+ {
+ out += '.';
+ using MilliDuration = std::chrono::duration<int, std::milli>;
+ MilliDuration subsec = duration_cast<MilliDuration>(t);
+ out += details::padZeros(subsec.count(), 3);
+ }
+ else if constexpr (std::is_same_v<typename decltype(t)::period, std::micro>)
+ {
+ out += '.';
+
+ using MicroDuration = std::chrono::duration<int, std::micro>;
+ MicroDuration subsec = duration_cast<MicroDuration>(t);
+ out += details::padZeros(subsec.count(), 6);
+ }
+
+ out += "+00:00";
+ return out;
+}
+} // namespace details
+
+// Returns the formatted date time string.
+// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
+// the given |secondsSinceEpoch| is too large, we return the maximum supported
+// date.
+inline std::string getDateTimeUint(uint64_t secondsSinceEpoch)
+{
+ using DurationType = std::chrono::duration<uint64_t>;
+ DurationType sinceEpoch(secondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
+}
+
+// Returns the formatted date time string with millisecond precision
+// Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if
+// the given |secondsSinceEpoch| is too large, we return the maximum supported
+// date.
+inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch)
+{
+ using DurationType = std::chrono::duration<uint64_t, std::milli>;
+ DurationType sinceEpoch(milliSecondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
+}
+
+// Returns the formatted date time string with microsecond precision
+inline std::string getDateTimeUintUs(uint64_t microSecondsSinceEpoch)
+{
+ using DurationType = std::chrono::duration<uint64_t, std::micro>;
+ DurationType sinceEpoch(microSecondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
+}
+
+inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch)
+{
+ using DurationType = std::chrono::duration<std::time_t>;
+ DurationType sinceEpoch(secondsSinceEpoch);
+ return details::toISO8061ExtendedStr(sinceEpoch);
+}
+
+/**
+ * Returns the current Date, Time & the local Time Offset
+ * infromation in a pair
+ *
+ * @param[in] None
+ *
+ * @return std::pair<std::string, std::string>, which consist
+ * of current DateTime & the TimeOffset strings respectively.
+ */
+inline std::pair<std::string, std::string> getDateTimeOffsetNow()
+{
+ std::time_t time = std::time(nullptr);
+ std::string dateTime = getDateTimeStdtime(time);
+
+ /* extract the local Time Offset value from the
+ * recevied dateTime string.
+ */
+ std::string timeOffset("Z00:00");
+ std::size_t lastPos = dateTime.size();
+ std::size_t len = timeOffset.size();
+ if (lastPos > len)
+ {
+ timeOffset = dateTime.substr(lastPos - len);
+ }
+
+ return std::make_pair(dateTime, timeOffset);
+}
+
} // namespace time_utils
} // namespace redfish
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index fc347dc..471b45a 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -690,7 +690,7 @@
if (value != nullptr)
{
asyncResp->res.jsonValue["ValidNotAfter"] =
- crow::utility::getDateTimeUint(*value);
+ redfish::time_utils::getDateTimeUint(*value);
}
}
else if (property.first == "ValidNotBefore")
@@ -699,7 +699,7 @@
if (value != nullptr)
{
asyncResp->res.jsonValue["ValidNotBefore"] =
- crow::utility::getDateTimeUint(*value);
+ redfish::time_utils::getDateTimeUint(*value);
}
}
}
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index e806bfa..32afd36 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -38,6 +38,7 @@
#include <error_messages.hpp>
#include <query.hpp>
#include <registries/privilege_registry.hpp>
+#include <utils/time_utils.hpp>
#include <charconv>
#include <filesystem>
@@ -178,7 +179,8 @@
<< strerror(-ret);
return false;
}
- entryTimestamp = crow::utility::getDateTimeUint(timestamp / 1000 / 1000);
+ entryTimestamp =
+ redfish::time_utils::getDateTimeUint(timestamp / 1000 / 1000);
return true;
}
@@ -495,7 +497,8 @@
thisEntry["@odata.id"] = entriesPath + entryID;
thisEntry["Id"] = entryID;
thisEntry["EntryType"] = "Event";
- thisEntry["Created"] = crow::utility::getDateTimeUint(timestamp);
+ thisEntry["Created"] =
+ redfish::time_utils::getDateTimeUint(timestamp);
thisEntry["Name"] = dumpType + " Dump Entry";
if (dumpType == "BMC")
@@ -580,7 +583,7 @@
asyncResp->res.jsonValue["Id"] = entryID;
asyncResp->res.jsonValue["EntryType"] = "Event";
asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTimeUint(timestamp);
+ redfish::time_utils::getDateTimeUint(timestamp);
asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
if (dumpType == "BMC")
@@ -990,7 +993,7 @@
asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
@@ -1442,9 +1445,9 @@
thisEntry["Severity"] =
translateSeverityDbusToRedfish(*severity);
thisEntry["Created"] =
- crow::utility::getDateTimeUintMs(*timestamp);
+ redfish::time_utils::getDateTimeUintMs(*timestamp);
thisEntry["Modified"] =
- crow::utility::getDateTimeUintMs(*updateTimestamp);
+ redfish::time_utils::getDateTimeUintMs(*updateTimestamp);
if (filePath != nullptr)
{
thisEntry["AdditionalDataURI"] =
@@ -1565,9 +1568,9 @@
asyncResp->res.jsonValue["Severity"] =
translateSeverityDbusToRedfish(*severity);
asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTimeUintMs(*timestamp);
+ redfish::time_utils::getDateTimeUintMs(*timestamp);
asyncResp->res.jsonValue["Modified"] =
- crow::utility::getDateTimeUintMs(*updateTimestamp);
+ redfish::time_utils::getDateTimeUintMs(*updateTimestamp);
if (filePath != nullptr)
{
asyncResp->res.jsonValue["AdditionalDataURI"] =
@@ -2106,7 +2109,7 @@
asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
redfishDateTimeOffset.second;
@@ -2378,7 +2381,7 @@
asyncResp->res.jsonValue["OverWritePolicy"] = std::move(overWritePolicy);
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
redfishDateTimeOffset.second;
@@ -2578,7 +2581,7 @@
asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
redfishDateTimeOffset.second;
@@ -2712,7 +2715,7 @@
asyncResp->res.jsonValue["MaxNumberOfRecords"] = 3;
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
redfishDateTimeOffset.second;
@@ -3195,7 +3198,7 @@
"/redfish/v1/Systems/system/LogServices/PostCodes/Entries";
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
redfishDateTimeOffset.second;
@@ -3302,7 +3305,7 @@
// Get the Created time from the timestamp
std::string entryTimeStr;
entryTimeStr =
- crow::utility::getDateTimeUint(usecSinceEpoch / 1000 / 1000);
+ redfish::time_utils::getDateTimeUint(usecSinceEpoch / 1000 / 1000);
// assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
std::ostringstream hexCode;
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index a98ff22..b8fe156 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -24,6 +24,7 @@
#include "utils/dbus_utils.hpp"
#include "utils/sw_utils.hpp"
#include "utils/systemd_utils.hpp"
+#include "utils/time_utils.hpp"
#include <boost/date_time.hpp>
#include <sdbusplus/asio/property.hpp>
@@ -1750,7 +1751,7 @@
// Convert to ISO 8601 standard
aResp->res.jsonValue["LastResetTime"] =
- crow::utility::getDateTimeUint(lastResetTimeStamp);
+ redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
});
}
@@ -1984,7 +1985,7 @@
resetToDefaults["ResetType@Redfish.AllowableValues"] = {"ResetAll"};
std::pair<std::string, std::string> redfishDateTimeOffset =
- crow::utility::getDateTimeOffsetNow();
+ redfish::time_utils::getDateTimeOffsetNow();
asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
asyncResp->res.jsonValue["DateTimeLocalOffset"] =
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index b93483c..18830f1 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -2,6 +2,7 @@
#include "utils/collection.hpp"
#include "utils/telemetry_utils.hpp"
+#include "utils/time_utils.hpp"
#include <app.hpp>
#include <dbus_utility.hpp>
@@ -32,7 +33,7 @@
{"MetricId", id},
{"MetricProperty", metadata},
{"MetricValue", std::to_string(sensorValue)},
- {"Timestamp", crow::utility::getDateTimeUintMs(timestamp)},
+ {"Timestamp", redfish::time_utils::getDateTimeUintMs(timestamp)},
});
}
@@ -55,7 +56,7 @@
.string();
const auto& [timestamp, readings] = timestampReadings;
- json["Timestamp"] = crow::utility::getDateTimeUintMs(timestamp);
+ json["Timestamp"] = redfish::time_utils::getDateTimeUintMs(timestamp);
json["MetricValues"] = toMetricValues(readings);
return true;
}
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index dd58e1b..0c2c53c 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -21,6 +21,7 @@
#include "pcie.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
+#include "utils/time_utils.hpp"
#include <app.hpp>
#include <boost/container/flat_map.hpp>
@@ -1079,7 +1080,7 @@
// Convert to ISO 8601 standard
aResp->res.jsonValue["LastResetTime"] =
- crow::utility::getDateTimeUint(lastResetTimeStamp);
+ redfish::time_utils::getDateTimeUint(lastResetTimeStamp);
});
}
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 7d96e42..be48a5b 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -395,11 +395,11 @@
asyncResp->res.jsonValue["Name"] = "Task " + strParam;
asyncResp->res.jsonValue["TaskState"] = ptr->state;
asyncResp->res.jsonValue["StartTime"] =
- crow::utility::getDateTimeStdtime(ptr->startTime);
+ redfish::time_utils::getDateTimeStdtime(ptr->startTime);
if (ptr->endTime)
{
asyncResp->res.jsonValue["EndTime"] =
- crow::utility::getDateTimeStdtime(*(ptr->endTime));
+ redfish::time_utils::getDateTimeStdtime(*(ptr->endTime));
}
asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
asyncResp->res.jsonValue["Messages"] = ptr->messages;
@@ -473,7 +473,7 @@
asyncResp->res.jsonValue["Name"] = "Task Service";
asyncResp->res.jsonValue["Id"] = "TaskService";
asyncResp->res.jsonValue["DateTime"] =
- crow::utility::getDateTimeOffsetNow().first;
+ redfish::time_utils::getDateTimeOffsetNow().first;
asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest";
asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true;
diff --git a/redfish-core/ut/time_utils_test.cpp b/redfish-core/ut/time_utils_test.cpp
index e390fbd..035d8ce 100644
--- a/redfish-core/ut/time_utils_test.cpp
+++ b/redfish-core/ut/time_utils_test.cpp
@@ -82,5 +82,62 @@
std::nullopt);
}
+TEST(GetDateTimeStdtime, ConversionTests)
+{
+ // some time before the epoch
+ EXPECT_EQ(getDateTimeStdtime(std::time_t{-1234567}),
+ "1970-01-01T00:00:00+00:00");
+
+ // epoch
+ EXPECT_EQ(getDateTimeStdtime(std::time_t{0}), "1970-01-01T00:00:00+00:00");
+
+ // Limits
+ EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::max()),
+ "9999-12-31T23:59:59+00:00");
+ EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::min()),
+ "1970-01-01T00:00:00+00:00");
+}
+
+TEST(GetDateTimeUint, ConversionTests)
+{
+ EXPECT_EQ(getDateTimeUint(uint64_t{1638312095}),
+ "2021-11-30T22:41:35+00:00");
+ // some time in the future, beyond 2038
+ EXPECT_EQ(getDateTimeUint(uint64_t{41638312095}),
+ "3289-06-18T21:48:15+00:00");
+ // the maximum time we support
+ EXPECT_EQ(getDateTimeUint(uint64_t{253402300799}),
+ "9999-12-31T23:59:59+00:00");
+
+ // returns the maximum Redfish date
+ EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::max()),
+ "9999-12-31T23:59:59+00:00");
+
+ EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::min()),
+ "1970-01-01T00:00:00+00:00");
+}
+
+TEST(GetDateTimeUintMs, ConverstionTests)
+{
+ EXPECT_EQ(getDateTimeUintMs(uint64_t{1638312095123}),
+ "2021-11-30T22:41:35.123+00:00");
+ // returns the maximum Redfish date
+ EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::max()),
+ "9999-12-31T23:59:59.999+00:00");
+ EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::min()),
+ "1970-01-01T00:00:00.000+00:00");
+}
+
+TEST(Utility, GetDateTimeUintUs)
+{
+ EXPECT_EQ(getDateTimeUintUs(uint64_t{1638312095123456}),
+ "2021-11-30T22:41:35.123456+00:00");
+ // returns the maximum Redfish date
+ EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::max()),
+ "9999-12-31T23:59:59.999999+00:00");
+ EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::min()),
+ "1970-01-01T00:00:00.000000+00:00");
+}
+
} // namespace
} // namespace redfish::time_utils