1 #pragma once
2 
3 #include <chrono>
4 #include <string>
5 
6 namespace redfish
7 {
8 
9 namespace time_utils
10 {
11 
12 namespace details
13 {
14 
15 inline void leftZeroPadding(std::string& str, const std::size_t padding)
16 {
17     if (str.size() < padding)
18     {
19         str.insert(0, padding - str.size(), '0');
20     }
21 }
22 } // namespace details
23 
24 /**
25  * @brief Convert time value into duration format that is based on ISO 8601.
26  *        Example output: "P12DT1M5.5S"
27  *        Ref: Redfish Specification, Section 9.4.4. Duration values
28  */
29 inline std::string toDurationString(std::chrono::milliseconds ms)
30 {
31     if (ms < std::chrono::milliseconds::zero())
32     {
33         return "";
34     }
35 
36     std::string fmt;
37     fmt.reserve(sizeof("PxxxxxxxxxxxxDTxxHxxMxx.xxxxxxS"));
38 
39     using Days = std::chrono::duration<long, std::ratio<24 * 60 * 60>>;
40     Days days = std::chrono::floor<Days>(ms);
41     ms -= days;
42 
43     std::chrono::hours hours = std::chrono::floor<std::chrono::hours>(ms);
44     ms -= hours;
45 
46     std::chrono::minutes minutes = std::chrono::floor<std::chrono::minutes>(ms);
47     ms -= minutes;
48 
49     std::chrono::seconds seconds = std::chrono::floor<std::chrono::seconds>(ms);
50     ms -= seconds;
51 
52     fmt = "P";
53     if (days.count() > 0)
54     {
55         fmt += std::to_string(days.count()) + "D";
56     }
57     fmt += "T";
58     if (hours.count() > 0)
59     {
60         fmt += std::to_string(hours.count()) + "H";
61     }
62     if (minutes.count() > 0)
63     {
64         fmt += std::to_string(minutes.count()) + "M";
65     }
66     if (seconds.count() != 0 || ms.count() != 0)
67     {
68         fmt += std::to_string(seconds.count()) + ".";
69         std::string msStr = std::to_string(ms.count());
70         details::leftZeroPadding(msStr, 3);
71         fmt += msStr + "S";
72     }
73 
74     return fmt;
75 }
76 
77 } // namespace time_utils
78 } // namespace redfish
79