Refactoring: Changed all check parameters starting with a 'p' to the new rulespec...
[check_mk.git] / livestatus / src / ChronoUtils.h
blob0b0b13e72b4268906569aaa477e39175206481e8
1 // +------------------------------------------------------------------+
2 // | ____ _ _ __ __ _ __ |
3 // | / ___| |__ ___ ___| | __ | \/ | |/ / |
4 // | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
5 // | | |___| | | | __/ (__| < | | | | . \ |
6 // | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
7 // | |
8 // | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
14 // check_mk is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by
16 // the Free Software Foundation in version 2. check_mk is distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
18 // out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 // PARTICULAR PURPOSE. See the GNU General Public License for more de-
20 // tails. You should have received a copy of the GNU General Public
21 // License along with GNU Make; see the file COPYING. If not, write
22 // to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 // Boston, MA 02110-1301 USA.
25 #ifndef ChronoUtils_h
26 #define ChronoUtils_h
28 #include "config.h" // IWYU pragma: keep
29 #include <chrono>
30 #include <cstdlib>
31 #include <ctime>
32 #include <iomanip>
33 #include <ratio>
34 #include <string>
35 #include <utility>
37 using minutes_d = std::chrono::duration<double, std::ratio<60>>;
39 inline double elapsed_ms_since(std::chrono::steady_clock::time_point then) {
40 return std::chrono::duration_cast<
41 std::chrono::duration<double, std::milli>>(
42 std::chrono::steady_clock::now() - then)
43 .count();
46 inline tm to_tm(std::chrono::system_clock::time_point tp) {
47 time_t t = std::chrono::system_clock::to_time_t(tp);
48 struct tm ret;
49 // NOTE: A brilliant example of how to make a simple API function a total
50 // chaos follows...
51 #if defined(__STDC_LIB_EXT1__)
52 // C11 function, only guaranteed to be available when a
53 // #define __STDC_WANT_LIB_EXT1_ 1
54 // is done before including <time.h>. Signature:
55 // struct tm *localtime_s(const time_t *restrict timer,
56 // struct tm *restrict result)
57 localtime_s(&t, &ret);
58 #elif defined(__WIN32)
59 // Win32 variant, it keeps us entertained with swapped parameters and a
60 // different return value, yay! Signature:
61 // errno_t localtime_s(struct tm* _tm, const time_t *time)
62 // We have to de-confuse cppcheck:
63 // cppcheck-suppress uninitvar
64 localtime_s(&ret, &t);
65 #else
66 // POSIX.1-2008 variant, available under MinGW64 only under obscure
67 // circumstances, so better avoid it there. Signature:
68 // struct tm *localtime_r(const time_t *restrict timer,
69 // struct tm *restrict result);
70 localtime_r(&t, &ret);
71 #endif
72 // Reason: see Win32 section above
73 // cppcheck-suppress uninitvar
74 return ret;
77 inline std::chrono::system_clock::time_point from_tm(tm tp) {
78 return std::chrono::system_clock::from_time_t(mktime(&tp));
81 template <typename Rep, typename Period>
82 inline timeval to_timeval(std::chrono::duration<Rep, Period> dur) {
83 timeval tv;
84 // NOTE: The static_casts below are needed to avoid warning on e.g. some
85 // 32bit platforms, because the underlying types might be larger than the
86 // timeval fields. We can't use the correct POSIX types time_t and
87 // suseconds_t because of the broken MinGW cross compiler, so we revert to
88 // decltype.
89 tv.tv_sec = static_cast<decltype(tv.tv_sec)>(
90 std::chrono::duration_cast<std::chrono::seconds>(dur).count());
91 tv.tv_usec = static_cast<decltype(tv.tv_usec)>(
92 std::chrono::duration_cast<std::chrono::microseconds>(
93 dur % std::chrono::seconds(1))
94 .count());
95 return tv;
98 inline std::chrono::system_clock::time_point from_timeval(const timeval &tv) {
99 return std::chrono::system_clock::time_point(
100 std::chrono::seconds(tv.tv_sec) +
101 std::chrono::microseconds(tv.tv_usec));
104 inline std::chrono::system_clock::time_point parse_time_t(
105 const std::string &str) {
106 return std::chrono::system_clock::from_time_t(atoi(str.c_str()));
109 template <typename Dur>
110 typename Dur::rep time_point_part(std::chrono::system_clock::time_point &tp) {
111 return std::chrono::duration_cast<Dur>(tp.time_since_epoch() % Dur(1000))
112 .count();
115 class FormattedTimePoint {
116 public:
117 explicit FormattedTimePoint(std::chrono::system_clock::time_point tp,
118 std::string format = default_format)
119 : _tp(tp), _format(std::move(format)) {}
120 explicit FormattedTimePoint(time_t t, std::string format = default_format)
121 : _tp(std::chrono::system_clock::from_time_t(t))
122 , _format(std::move(format)) {}
124 friend std::ostream &operator<<(std::ostream &os,
125 const FormattedTimePoint &f) {
126 tm local = to_tm(f._tp);
127 return os << std::put_time(&local, f._format.c_str());
130 private:
131 std::chrono::system_clock::time_point _tp;
132 std::string _format;
134 // NOTE: In a perfect world we would simply use "%F %T" below, but the "%F"
135 // format is a C99 addition, and the "%T" format is part of The Single Unix
136 // Specification. Both formats should be available in any C++11-compliant
137 // compiler, but the MinGW cross compiler doesn't get this right. So let's
138 // use their ancient expansions...
139 static constexpr auto default_format = "%Y-%m-%d %H:%M:%S";
142 #endif // ChronoUtils_h