xref: /openbmc/bmcweb/features/redfish/src/utils/time_utils.cpp (revision 1b8b02a4ab0aae072d0891301d1f9d5376e7912b)
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