1081ebf06SWludzik, Jozef #pragma once 2081ebf06SWludzik, Jozef 34dbb8aeaSWludzik, Jozef #include "logging.hpp" 44dbb8aeaSWludzik, Jozef 59ea15c35SEd Tanous #include <algorithm> 64dbb8aeaSWludzik, Jozef #include <charconv> 7081ebf06SWludzik, Jozef #include <chrono> 84dbb8aeaSWludzik, Jozef #include <cmath> 99ea15c35SEd Tanous #include <compare> 109ea15c35SEd Tanous #include <cstddef> 11d5c80ad9SNan Zhou #include <cstdint> 124dbb8aeaSWludzik, Jozef #include <optional> 139ea15c35SEd Tanous #include <ratio> 14081ebf06SWludzik, Jozef #include <string> 159ea15c35SEd Tanous #include <string_view> 164dbb8aeaSWludzik, Jozef #include <system_error> 17081ebf06SWludzik, Jozef 18d5c80ad9SNan Zhou // IWYU pragma: no_include <stddef.h> 19d5c80ad9SNan Zhou // IWYU pragma: no_include <stdint.h> 20d5c80ad9SNan Zhou 21081ebf06SWludzik, Jozef namespace redfish 22081ebf06SWludzik, Jozef { 23081ebf06SWludzik, Jozef 24081ebf06SWludzik, Jozef namespace time_utils 25081ebf06SWludzik, Jozef { 26081ebf06SWludzik, Jozef 27081ebf06SWludzik, Jozef namespace details 28081ebf06SWludzik, Jozef { 29081ebf06SWludzik, Jozef 306de264ccSEd Tanous constexpr intmax_t dayDuration = static_cast<intmax_t>(24 * 60 * 60); 316de264ccSEd Tanous using Days = std::chrono::duration<long long, std::ratio<dayDuration>>; 324dbb8aeaSWludzik, Jozef 33081ebf06SWludzik, Jozef inline void leftZeroPadding(std::string& str, const std::size_t padding) 34081ebf06SWludzik, Jozef { 35081ebf06SWludzik, Jozef if (str.size() < padding) 36081ebf06SWludzik, Jozef { 37081ebf06SWludzik, Jozef str.insert(0, padding - str.size(), '0'); 38081ebf06SWludzik, Jozef } 39081ebf06SWludzik, Jozef } 404dbb8aeaSWludzik, Jozef 414dbb8aeaSWludzik, Jozef template <typename FromTime> 424dbb8aeaSWludzik, Jozef bool fromDurationItem(std::string_view& fmt, const char postfix, 434dbb8aeaSWludzik, Jozef std::chrono::milliseconds& out) 444dbb8aeaSWludzik, Jozef { 454dbb8aeaSWludzik, Jozef const size_t pos = fmt.find(postfix); 464dbb8aeaSWludzik, Jozef if (pos == std::string::npos) 474dbb8aeaSWludzik, Jozef { 484dbb8aeaSWludzik, Jozef return true; 494dbb8aeaSWludzik, Jozef } 504dbb8aeaSWludzik, Jozef if ((pos + 1U) > fmt.size()) 514dbb8aeaSWludzik, Jozef { 524dbb8aeaSWludzik, Jozef return false; 534dbb8aeaSWludzik, Jozef } 544dbb8aeaSWludzik, Jozef 55543f4400SEd Tanous const char* end = nullptr; 564dbb8aeaSWludzik, Jozef std::chrono::milliseconds::rep ticks = 0; 574dbb8aeaSWludzik, Jozef if constexpr (std::is_same_v<FromTime, std::chrono::milliseconds>) 584dbb8aeaSWludzik, Jozef { 594dbb8aeaSWludzik, Jozef end = fmt.data() + std::min<size_t>(pos, 3U); 604dbb8aeaSWludzik, Jozef } 614dbb8aeaSWludzik, Jozef else 624dbb8aeaSWludzik, Jozef { 634dbb8aeaSWludzik, Jozef end = fmt.data() + pos; 644dbb8aeaSWludzik, Jozef } 654dbb8aeaSWludzik, Jozef 664dbb8aeaSWludzik, Jozef auto [ptr, ec] = std::from_chars(fmt.data(), end, ticks); 674dbb8aeaSWludzik, Jozef if (ptr != end || ec != std::errc()) 684dbb8aeaSWludzik, Jozef { 694dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Failed to convert string to decimal with err: " 704dbb8aeaSWludzik, Jozef << static_cast<int>(ec) << "(" 714dbb8aeaSWludzik, Jozef << std::make_error_code(ec).message() << "), ptr{" 724dbb8aeaSWludzik, Jozef << static_cast<const void*>(ptr) << "} != end{" 734dbb8aeaSWludzik, Jozef << static_cast<const void*>(end) << "})"; 744dbb8aeaSWludzik, Jozef return false; 754dbb8aeaSWludzik, Jozef } 764dbb8aeaSWludzik, Jozef 774dbb8aeaSWludzik, Jozef if constexpr (std::is_same_v<FromTime, std::chrono::milliseconds>) 784dbb8aeaSWludzik, Jozef { 794dbb8aeaSWludzik, Jozef ticks *= static_cast<std::chrono::milliseconds::rep>( 804dbb8aeaSWludzik, Jozef std::pow(10, 3 - std::min<size_t>(pos, 3U))); 814dbb8aeaSWludzik, Jozef } 824dbb8aeaSWludzik, Jozef if (ticks < 0) 834dbb8aeaSWludzik, Jozef { 844dbb8aeaSWludzik, Jozef return false; 854dbb8aeaSWludzik, Jozef } 864dbb8aeaSWludzik, Jozef 874dbb8aeaSWludzik, Jozef out += FromTime(ticks); 884dbb8aeaSWludzik, Jozef const auto maxConversionRange = 894dbb8aeaSWludzik, Jozef std::chrono::duration_cast<FromTime>(std::chrono::milliseconds::max()) 904dbb8aeaSWludzik, Jozef .count(); 914dbb8aeaSWludzik, Jozef if (out < FromTime(ticks) || maxConversionRange < ticks) 924dbb8aeaSWludzik, Jozef { 934dbb8aeaSWludzik, Jozef return false; 944dbb8aeaSWludzik, Jozef } 954dbb8aeaSWludzik, Jozef 964dbb8aeaSWludzik, Jozef fmt.remove_prefix(pos + 1U); 974dbb8aeaSWludzik, Jozef return true; 984dbb8aeaSWludzik, Jozef } 99081ebf06SWludzik, Jozef } // namespace details 100081ebf06SWludzik, Jozef 101081ebf06SWludzik, Jozef /** 1024dbb8aeaSWludzik, Jozef * @brief Convert string that represents value in Duration Format to its numeric 1034dbb8aeaSWludzik, Jozef * equivalent. 1044dbb8aeaSWludzik, Jozef */ 1054f48d5f6SEd Tanous inline std::optional<std::chrono::milliseconds> 1064dbb8aeaSWludzik, Jozef fromDurationString(const std::string& str) 1074dbb8aeaSWludzik, Jozef { 1084dbb8aeaSWludzik, Jozef std::chrono::milliseconds out = std::chrono::milliseconds::zero(); 1094dbb8aeaSWludzik, Jozef std::string_view v = str; 1104dbb8aeaSWludzik, Jozef 1114dbb8aeaSWludzik, Jozef if (v.empty()) 1124dbb8aeaSWludzik, Jozef { 1134dbb8aeaSWludzik, Jozef return out; 1144dbb8aeaSWludzik, Jozef } 1154dbb8aeaSWludzik, Jozef if (v.front() != 'P') 1164dbb8aeaSWludzik, Jozef { 1174dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1184dbb8aeaSWludzik, Jozef return std::nullopt; 1194dbb8aeaSWludzik, Jozef } 1204dbb8aeaSWludzik, Jozef 1214dbb8aeaSWludzik, Jozef v.remove_prefix(1); 1224dbb8aeaSWludzik, Jozef if (!details::fromDurationItem<details::Days>(v, 'D', out)) 1234dbb8aeaSWludzik, Jozef { 1244dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1254dbb8aeaSWludzik, Jozef return std::nullopt; 1264dbb8aeaSWludzik, Jozef } 1274dbb8aeaSWludzik, Jozef 1284dbb8aeaSWludzik, Jozef if (v.empty()) 1294dbb8aeaSWludzik, Jozef { 1304dbb8aeaSWludzik, Jozef return out; 1314dbb8aeaSWludzik, Jozef } 1324dbb8aeaSWludzik, Jozef if (v.front() != 'T') 1334dbb8aeaSWludzik, Jozef { 1344dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1354dbb8aeaSWludzik, Jozef return std::nullopt; 1364dbb8aeaSWludzik, Jozef } 1374dbb8aeaSWludzik, Jozef 1384dbb8aeaSWludzik, Jozef v.remove_prefix(1); 1394dbb8aeaSWludzik, Jozef if (!details::fromDurationItem<std::chrono::hours>(v, 'H', out) || 1404dbb8aeaSWludzik, Jozef !details::fromDurationItem<std::chrono::minutes>(v, 'M', out)) 1414dbb8aeaSWludzik, Jozef { 1424dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1434dbb8aeaSWludzik, Jozef return std::nullopt; 1444dbb8aeaSWludzik, Jozef } 1454dbb8aeaSWludzik, Jozef 1464dbb8aeaSWludzik, Jozef if (v.find('.') != std::string::npos && v.find('S') != std::string::npos) 1474dbb8aeaSWludzik, Jozef { 1484dbb8aeaSWludzik, Jozef if (!details::fromDurationItem<std::chrono::seconds>(v, '.', out) || 1494dbb8aeaSWludzik, Jozef !details::fromDurationItem<std::chrono::milliseconds>(v, 'S', out)) 1504dbb8aeaSWludzik, Jozef { 1514dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1524dbb8aeaSWludzik, Jozef return std::nullopt; 1534dbb8aeaSWludzik, Jozef } 1544dbb8aeaSWludzik, Jozef } 1554dbb8aeaSWludzik, Jozef else if (!details::fromDurationItem<std::chrono::seconds>(v, 'S', out)) 1564dbb8aeaSWludzik, Jozef { 1574dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1584dbb8aeaSWludzik, Jozef return std::nullopt; 1594dbb8aeaSWludzik, Jozef } 1604dbb8aeaSWludzik, Jozef 1614dbb8aeaSWludzik, Jozef if (!v.empty()) 1624dbb8aeaSWludzik, Jozef { 1634dbb8aeaSWludzik, Jozef BMCWEB_LOG_ERROR << "Invalid duration format: " << str; 1644dbb8aeaSWludzik, Jozef return std::nullopt; 1654dbb8aeaSWludzik, Jozef } 1664dbb8aeaSWludzik, Jozef return out; 1674dbb8aeaSWludzik, Jozef } 1684dbb8aeaSWludzik, Jozef 1694dbb8aeaSWludzik, Jozef /** 170081ebf06SWludzik, Jozef * @brief Convert time value into duration format that is based on ISO 8601. 171081ebf06SWludzik, Jozef * Example output: "P12DT1M5.5S" 172081ebf06SWludzik, Jozef * Ref: Redfish Specification, Section 9.4.4. Duration values 173081ebf06SWludzik, Jozef */ 174b00dcc27SEd Tanous inline std::string toDurationString(std::chrono::milliseconds ms) 175081ebf06SWludzik, Jozef { 176081ebf06SWludzik, Jozef if (ms < std::chrono::milliseconds::zero()) 177081ebf06SWludzik, Jozef { 178081ebf06SWludzik, Jozef return ""; 179081ebf06SWludzik, Jozef } 180081ebf06SWludzik, Jozef 181081ebf06SWludzik, Jozef std::string fmt; 182081ebf06SWludzik, Jozef fmt.reserve(sizeof("PxxxxxxxxxxxxDTxxHxxMxx.xxxxxxS")); 183081ebf06SWludzik, Jozef 1844dbb8aeaSWludzik, Jozef details::Days days = std::chrono::floor<details::Days>(ms); 185081ebf06SWludzik, Jozef ms -= days; 186081ebf06SWludzik, Jozef 187081ebf06SWludzik, Jozef std::chrono::hours hours = std::chrono::floor<std::chrono::hours>(ms); 188081ebf06SWludzik, Jozef ms -= hours; 189081ebf06SWludzik, Jozef 190081ebf06SWludzik, Jozef std::chrono::minutes minutes = std::chrono::floor<std::chrono::minutes>(ms); 191081ebf06SWludzik, Jozef ms -= minutes; 192081ebf06SWludzik, Jozef 193081ebf06SWludzik, Jozef std::chrono::seconds seconds = std::chrono::floor<std::chrono::seconds>(ms); 194081ebf06SWludzik, Jozef ms -= seconds; 195081ebf06SWludzik, Jozef 196081ebf06SWludzik, Jozef fmt = "P"; 197081ebf06SWludzik, Jozef if (days.count() > 0) 198081ebf06SWludzik, Jozef { 199081ebf06SWludzik, Jozef fmt += std::to_string(days.count()) + "D"; 200081ebf06SWludzik, Jozef } 201081ebf06SWludzik, Jozef fmt += "T"; 202081ebf06SWludzik, Jozef if (hours.count() > 0) 203081ebf06SWludzik, Jozef { 204081ebf06SWludzik, Jozef fmt += std::to_string(hours.count()) + "H"; 205081ebf06SWludzik, Jozef } 206081ebf06SWludzik, Jozef if (minutes.count() > 0) 207081ebf06SWludzik, Jozef { 208081ebf06SWludzik, Jozef fmt += std::to_string(minutes.count()) + "M"; 209081ebf06SWludzik, Jozef } 210081ebf06SWludzik, Jozef if (seconds.count() != 0 || ms.count() != 0) 211081ebf06SWludzik, Jozef { 212081ebf06SWludzik, Jozef fmt += std::to_string(seconds.count()) + "."; 213081ebf06SWludzik, Jozef std::string msStr = std::to_string(ms.count()); 214081ebf06SWludzik, Jozef details::leftZeroPadding(msStr, 3); 215081ebf06SWludzik, Jozef fmt += msStr + "S"; 216081ebf06SWludzik, Jozef } 217081ebf06SWludzik, Jozef 218081ebf06SWludzik, Jozef return fmt; 219081ebf06SWludzik, Jozef } 220081ebf06SWludzik, Jozef 2211b7e696bSLukasz Kazmierczak inline std::optional<std::string> 2221b7e696bSLukasz Kazmierczak toDurationStringFromUint(const uint64_t timeMs) 2231b7e696bSLukasz Kazmierczak { 2241b7e696bSLukasz Kazmierczak static const uint64_t maxTimeMs = 2251b7e696bSLukasz Kazmierczak static_cast<uint64_t>(std::chrono::milliseconds::max().count()); 2261b7e696bSLukasz Kazmierczak 2271b7e696bSLukasz Kazmierczak if (maxTimeMs < timeMs) 2281b7e696bSLukasz Kazmierczak { 2291b7e696bSLukasz Kazmierczak return std::nullopt; 2301b7e696bSLukasz Kazmierczak } 2311b7e696bSLukasz Kazmierczak 2321b7e696bSLukasz Kazmierczak std::string duration = toDurationString(std::chrono::milliseconds(timeMs)); 2331b7e696bSLukasz Kazmierczak if (duration.empty()) 2341b7e696bSLukasz Kazmierczak { 2351b7e696bSLukasz Kazmierczak return std::nullopt; 2361b7e696bSLukasz Kazmierczak } 2371b7e696bSLukasz Kazmierczak 2381b7e696bSLukasz Kazmierczak return std::make_optional(duration); 2391b7e696bSLukasz Kazmierczak } 2401b7e696bSLukasz Kazmierczak 241*2b82937eSEd Tanous namespace details 242*2b82937eSEd Tanous { 243*2b82937eSEd Tanous // Returns year/month/day triple in civil calendar 244*2b82937eSEd Tanous // Preconditions: z is number of days since 1970-01-01 and is in the range: 245*2b82937eSEd Tanous // [numeric_limits<Int>::min(), 246*2b82937eSEd Tanous // numeric_limits<Int>::max()-719468]. 247*2b82937eSEd Tanous // Algorithm sourced from 248*2b82937eSEd Tanous // https://howardhinnant.github.io/date_algorithms.html#civil_from_days 249*2b82937eSEd Tanous // All constants are explained in the above 250*2b82937eSEd Tanous template <class IntType> 251*2b82937eSEd Tanous constexpr std::tuple<IntType, unsigned, unsigned> 252*2b82937eSEd Tanous civilFromDays(IntType z) noexcept 253*2b82937eSEd Tanous { 254*2b82937eSEd Tanous z += 719468; 255*2b82937eSEd Tanous IntType era = (z >= 0 ? z : z - 146096) / 146097; 256*2b82937eSEd Tanous unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096] 257*2b82937eSEd Tanous unsigned yoe = 258*2b82937eSEd Tanous (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399] 259*2b82937eSEd Tanous IntType y = static_cast<IntType>(yoe) + era * 400; 260*2b82937eSEd Tanous unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365] 261*2b82937eSEd Tanous unsigned mp = (5 * doy + 2) / 153; // [0, 11] 262*2b82937eSEd Tanous unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31] 263*2b82937eSEd Tanous unsigned m = mp < 10 ? mp + 3 : mp - 9; // [1, 12] 264*2b82937eSEd Tanous 265*2b82937eSEd Tanous return std::tuple<IntType, unsigned, unsigned>(y + (m <= 2), m, d); 266*2b82937eSEd Tanous } 267*2b82937eSEd Tanous 268*2b82937eSEd Tanous // Creates a string from an integer in the most efficient way possible without 269*2b82937eSEd Tanous // using std::locale. Adds an exact zero pad based on the pad input parameter. 270*2b82937eSEd Tanous // Does nt handle negative numbers. 271*2b82937eSEd Tanous inline std::string padZeros(int value, size_t pad) 272*2b82937eSEd Tanous { 273*2b82937eSEd Tanous std::string result(pad, '0'); 274*2b82937eSEd Tanous for (int val = value; pad > 0; pad--) 275*2b82937eSEd Tanous { 276*2b82937eSEd Tanous result[pad - 1] = static_cast<char>('0' + val % 10); 277*2b82937eSEd Tanous val /= 10; 278*2b82937eSEd Tanous } 279*2b82937eSEd Tanous return result; 280*2b82937eSEd Tanous } 281*2b82937eSEd Tanous 282*2b82937eSEd Tanous template <typename IntType, typename Period> 283*2b82937eSEd Tanous std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t) 284*2b82937eSEd Tanous { 285*2b82937eSEd Tanous using seconds = std::chrono::duration<int>; 286*2b82937eSEd Tanous using minutes = std::chrono::duration<int, std::ratio<60>>; 287*2b82937eSEd Tanous using hours = std::chrono::duration<int, std::ratio<3600>>; 288*2b82937eSEd Tanous using days = std::chrono::duration< 289*2b82937eSEd Tanous IntType, std::ratio_multiply<hours::period, std::ratio<24>>>; 290*2b82937eSEd Tanous 291*2b82937eSEd Tanous // d is days since 1970-01-01 292*2b82937eSEd Tanous days d = std::chrono::duration_cast<days>(t); 293*2b82937eSEd Tanous 294*2b82937eSEd Tanous // t is now time duration since midnight of day d 295*2b82937eSEd Tanous t -= d; 296*2b82937eSEd Tanous 297*2b82937eSEd Tanous // break d down into year/month/day 298*2b82937eSEd Tanous int year = 0; 299*2b82937eSEd Tanous int month = 0; 300*2b82937eSEd Tanous int day = 0; 301*2b82937eSEd Tanous std::tie(year, month, day) = details::civilFromDays(d.count()); 302*2b82937eSEd Tanous // Check against limits. Can't go above year 9999, and can't go below epoch 303*2b82937eSEd Tanous // (1970) 304*2b82937eSEd Tanous if (year >= 10000) 305*2b82937eSEd Tanous { 306*2b82937eSEd Tanous year = 9999; 307*2b82937eSEd Tanous month = 12; 308*2b82937eSEd Tanous day = 31; 309*2b82937eSEd Tanous t = days(1) - std::chrono::duration<IntType, Period>(1); 310*2b82937eSEd Tanous } 311*2b82937eSEd Tanous else if (year < 1970) 312*2b82937eSEd Tanous { 313*2b82937eSEd Tanous year = 1970; 314*2b82937eSEd Tanous month = 1; 315*2b82937eSEd Tanous day = 1; 316*2b82937eSEd Tanous t = std::chrono::duration<IntType, Period>::zero(); 317*2b82937eSEd Tanous } 318*2b82937eSEd Tanous 319*2b82937eSEd Tanous std::string out; 320*2b82937eSEd Tanous out += details::padZeros(year, 4); 321*2b82937eSEd Tanous out += '-'; 322*2b82937eSEd Tanous out += details::padZeros(month, 2); 323*2b82937eSEd Tanous out += '-'; 324*2b82937eSEd Tanous out += details::padZeros(day, 2); 325*2b82937eSEd Tanous out += 'T'; 326*2b82937eSEd Tanous hours hr = duration_cast<hours>(t); 327*2b82937eSEd Tanous out += details::padZeros(hr.count(), 2); 328*2b82937eSEd Tanous t -= hr; 329*2b82937eSEd Tanous out += ':'; 330*2b82937eSEd Tanous 331*2b82937eSEd Tanous minutes mt = duration_cast<minutes>(t); 332*2b82937eSEd Tanous out += details::padZeros(mt.count(), 2); 333*2b82937eSEd Tanous t -= mt; 334*2b82937eSEd Tanous out += ':'; 335*2b82937eSEd Tanous 336*2b82937eSEd Tanous seconds se = duration_cast<seconds>(t); 337*2b82937eSEd Tanous out += details::padZeros(se.count(), 2); 338*2b82937eSEd Tanous t -= se; 339*2b82937eSEd Tanous 340*2b82937eSEd Tanous if constexpr (std::is_same_v<typename decltype(t)::period, std::milli>) 341*2b82937eSEd Tanous { 342*2b82937eSEd Tanous out += '.'; 343*2b82937eSEd Tanous using MilliDuration = std::chrono::duration<int, std::milli>; 344*2b82937eSEd Tanous MilliDuration subsec = duration_cast<MilliDuration>(t); 345*2b82937eSEd Tanous out += details::padZeros(subsec.count(), 3); 346*2b82937eSEd Tanous } 347*2b82937eSEd Tanous else if constexpr (std::is_same_v<typename decltype(t)::period, std::micro>) 348*2b82937eSEd Tanous { 349*2b82937eSEd Tanous out += '.'; 350*2b82937eSEd Tanous 351*2b82937eSEd Tanous using MicroDuration = std::chrono::duration<int, std::micro>; 352*2b82937eSEd Tanous MicroDuration subsec = duration_cast<MicroDuration>(t); 353*2b82937eSEd Tanous out += details::padZeros(subsec.count(), 6); 354*2b82937eSEd Tanous } 355*2b82937eSEd Tanous 356*2b82937eSEd Tanous out += "+00:00"; 357*2b82937eSEd Tanous return out; 358*2b82937eSEd Tanous } 359*2b82937eSEd Tanous } // namespace details 360*2b82937eSEd Tanous 361*2b82937eSEd Tanous // Returns the formatted date time string. 362*2b82937eSEd Tanous // Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if 363*2b82937eSEd Tanous // the given |secondsSinceEpoch| is too large, we return the maximum supported 364*2b82937eSEd Tanous // date. 365*2b82937eSEd Tanous inline std::string getDateTimeUint(uint64_t secondsSinceEpoch) 366*2b82937eSEd Tanous { 367*2b82937eSEd Tanous using DurationType = std::chrono::duration<uint64_t>; 368*2b82937eSEd Tanous DurationType sinceEpoch(secondsSinceEpoch); 369*2b82937eSEd Tanous return details::toISO8061ExtendedStr(sinceEpoch); 370*2b82937eSEd Tanous } 371*2b82937eSEd Tanous 372*2b82937eSEd Tanous // Returns the formatted date time string with millisecond precision 373*2b82937eSEd Tanous // Note that the maximum supported date is 9999-12-31T23:59:59+00:00, if 374*2b82937eSEd Tanous // the given |secondsSinceEpoch| is too large, we return the maximum supported 375*2b82937eSEd Tanous // date. 376*2b82937eSEd Tanous inline std::string getDateTimeUintMs(uint64_t milliSecondsSinceEpoch) 377*2b82937eSEd Tanous { 378*2b82937eSEd Tanous using DurationType = std::chrono::duration<uint64_t, std::milli>; 379*2b82937eSEd Tanous DurationType sinceEpoch(milliSecondsSinceEpoch); 380*2b82937eSEd Tanous return details::toISO8061ExtendedStr(sinceEpoch); 381*2b82937eSEd Tanous } 382*2b82937eSEd Tanous 383*2b82937eSEd Tanous // Returns the formatted date time string with microsecond precision 384*2b82937eSEd Tanous inline std::string getDateTimeUintUs(uint64_t microSecondsSinceEpoch) 385*2b82937eSEd Tanous { 386*2b82937eSEd Tanous using DurationType = std::chrono::duration<uint64_t, std::micro>; 387*2b82937eSEd Tanous DurationType sinceEpoch(microSecondsSinceEpoch); 388*2b82937eSEd Tanous return details::toISO8061ExtendedStr(sinceEpoch); 389*2b82937eSEd Tanous } 390*2b82937eSEd Tanous 391*2b82937eSEd Tanous inline std::string getDateTimeStdtime(std::time_t secondsSinceEpoch) 392*2b82937eSEd Tanous { 393*2b82937eSEd Tanous using DurationType = std::chrono::duration<std::time_t>; 394*2b82937eSEd Tanous DurationType sinceEpoch(secondsSinceEpoch); 395*2b82937eSEd Tanous return details::toISO8061ExtendedStr(sinceEpoch); 396*2b82937eSEd Tanous } 397*2b82937eSEd Tanous 398*2b82937eSEd Tanous /** 399*2b82937eSEd Tanous * Returns the current Date, Time & the local Time Offset 400*2b82937eSEd Tanous * infromation in a pair 401*2b82937eSEd Tanous * 402*2b82937eSEd Tanous * @param[in] None 403*2b82937eSEd Tanous * 404*2b82937eSEd Tanous * @return std::pair<std::string, std::string>, which consist 405*2b82937eSEd Tanous * of current DateTime & the TimeOffset strings respectively. 406*2b82937eSEd Tanous */ 407*2b82937eSEd Tanous inline std::pair<std::string, std::string> getDateTimeOffsetNow() 408*2b82937eSEd Tanous { 409*2b82937eSEd Tanous std::time_t time = std::time(nullptr); 410*2b82937eSEd Tanous std::string dateTime = getDateTimeStdtime(time); 411*2b82937eSEd Tanous 412*2b82937eSEd Tanous /* extract the local Time Offset value from the 413*2b82937eSEd Tanous * recevied dateTime string. 414*2b82937eSEd Tanous */ 415*2b82937eSEd Tanous std::string timeOffset("Z00:00"); 416*2b82937eSEd Tanous std::size_t lastPos = dateTime.size(); 417*2b82937eSEd Tanous std::size_t len = timeOffset.size(); 418*2b82937eSEd Tanous if (lastPos > len) 419*2b82937eSEd Tanous { 420*2b82937eSEd Tanous timeOffset = dateTime.substr(lastPos - len); 421*2b82937eSEd Tanous } 422*2b82937eSEd Tanous 423*2b82937eSEd Tanous return std::make_pair(dateTime, timeOffset); 424*2b82937eSEd Tanous } 425*2b82937eSEd Tanous 426081ebf06SWludzik, Jozef } // namespace time_utils 427081ebf06SWludzik, Jozef } // namespace redfish 428