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