1*1b8b02a4SEd Tanous #include "utils/time_utils.hpp" 2*1b8b02a4SEd Tanous 3*1b8b02a4SEd Tanous #include "utils/extern/date.h" 4*1b8b02a4SEd Tanous 5*1b8b02a4SEd Tanous #include <array> 6*1b8b02a4SEd Tanous #include <chrono> 7*1b8b02a4SEd Tanous #include <optional> 8*1b8b02a4SEd Tanous #include <sstream> 9*1b8b02a4SEd Tanous #include <string> 10*1b8b02a4SEd Tanous #include <string_view> 11*1b8b02a4SEd Tanous #include <version> 12*1b8b02a4SEd Tanous 13*1b8b02a4SEd Tanous namespace redfish::time_utils 14*1b8b02a4SEd Tanous { 15*1b8b02a4SEd Tanous using usSinceEpoch = std::chrono::duration<uint64_t, std::micro>; 16*1b8b02a4SEd Tanous std::optional<usSinceEpoch> dateStringToEpoch(std::string_view datetime) 17*1b8b02a4SEd Tanous { 18*1b8b02a4SEd Tanous for (const char* format : std::to_array({"%FT%T%Ez", "%FT%TZ", "%FT%T"})) 19*1b8b02a4SEd Tanous { 20*1b8b02a4SEd Tanous // Parse using signed so we can detect negative dates 21*1b8b02a4SEd Tanous std::chrono::sys_time<std::chrono::duration<int64_t, std::micro>> date; 22*1b8b02a4SEd Tanous std::istringstream iss(std::string{datetime}); 23*1b8b02a4SEd Tanous #if __cpp_lib_chrono >= 201907L 24*1b8b02a4SEd Tanous namespace chrono_from_stream = std::chrono; 25*1b8b02a4SEd Tanous #else 26*1b8b02a4SEd Tanous namespace chrono_from_stream = date; 27*1b8b02a4SEd Tanous #endif 28*1b8b02a4SEd Tanous if (chrono_from_stream::from_stream(iss, format, date)) 29*1b8b02a4SEd Tanous { 30*1b8b02a4SEd Tanous if (date.time_since_epoch().count() < 0) 31*1b8b02a4SEd Tanous { 32*1b8b02a4SEd Tanous return std::nullopt; 33*1b8b02a4SEd Tanous } 34*1b8b02a4SEd Tanous if (iss.rdbuf()->in_avail() != 0) 35*1b8b02a4SEd Tanous { 36*1b8b02a4SEd Tanous // More information left at end of string. 37*1b8b02a4SEd Tanous continue; 38*1b8b02a4SEd Tanous } 39*1b8b02a4SEd Tanous return usSinceEpoch{date.time_since_epoch().count()}; 40*1b8b02a4SEd Tanous } 41*1b8b02a4SEd Tanous } 42*1b8b02a4SEd Tanous return std::nullopt; 43*1b8b02a4SEd Tanous } 44*1b8b02a4SEd Tanous } // namespace redfish::time_utils 45