Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
1b5dfd98 TJ |
20 | /** @file |
21 | * @brief time related functions. | |
22 | * | |
d70f7269 | 23 | * @copyright Copyright © 2001-2018 by Intra2net AG |
1b5dfd98 | 24 | */ |
e93545dd GE |
25 | |
26 | #ifndef __TIMEFUNC_HXX | |
27 | #define __TIMEFUNC_HXX | |
28 | ||
e36ca33c | 29 | #include <climits> |
8b5814e2 | 30 | #include <errno.h> |
1b5dfd98 | 31 | #include <list> |
e36ca33c | 32 | #include <string> |
c42fd3b3 | 33 | #include <cstdlib> |
6d9ab467 | 34 | #include <algorithm> |
1b5dfd98 | 35 | |
8b5814e2 PG |
36 | #include <boost/optional.hpp> |
37 | ||
0c7e72d7 | 38 | #include <week.hpp> |
f1499910 | 39 | |
e36ca33c PG |
40 | #include "stringfunc.hxx" |
41 | ||
42 | #if __cplusplus >= 201103 | |
43 | # define CONSTEXPR constexpr | |
44 | # define NOEXCEPT noexcept | |
45 | #else | |
46 | # define CONSTEXPR | |
47 | # define NOEXCEPT | |
48 | #endif | |
49 | ||
50 | #define TIME_CONST_FACTOR_NANO (1000L * 1000 * 1000) | |
51 | ||
e93545dd GE |
52 | double prec_time(void); |
53 | ||
dad9e26f | 54 | time_t date_to_seconds(const std::string &date); |
e93545dd GE |
55 | |
56 | std::string make_nice_time(int seconds); | |
7839bd53 | 57 | std::string format_full_time(time_t seconds); |
25f3d405 | 58 | std::string format_date(time_t seconds); |
d70f7269 PG |
59 | std::string format_iso8601(const struct tm &tm, const bool date=true, |
60 | const bool time=true, const bool tz=true); | |
61 | std::string format_iso8601(time_t t, const bool utc=true, | |
62 | const bool date=true, const bool time=true, | |
63 | const bool tz=true); | |
9f39641d PG |
64 | |
65 | inline std::string format_iso8601(const struct timespec &ts, const bool utc=true, | |
d70f7269 PG |
66 | const bool date=true, const bool time=true, |
67 | const bool tz=true) | |
68 | { return format_iso8601 (ts.tv_sec, utc, date, time, tz); } | |
69 | ||
9f39641d PG |
70 | inline std::string format_sec_msec (const struct timespec &ts) |
71 | { | |
72 | return I2n::to_string (ts.tv_sec) + "s " | |
73 | + I2n::to_string (ts.tv_nsec / 1000000) + "ms" | |
74 | ; | |
75 | } | |
76 | ||
77 | boost::optional<std::string> format_min_sec_msec (const struct timespec &ts); | |
78 | ||
2795e39c PG |
79 | boost::optional<struct tm> scan_iso8601 (const char *s, |
80 | const bool date=true, const bool time=true, | |
81 | const bool tz=true) NOEXCEPT; | |
82 | inline boost::optional<struct tm> scan_iso8601 (const std::string &s, | |
83 | const bool date=true, | |
84 | const bool time=true, | |
85 | const bool tz=true) NOEXCEPT | |
86 | { return scan_iso8601 (s.c_str (), date, time, tz); } | |
87 | ||
88 | ||
87869870 | 89 | void seconds_to_hour_minute(int seconds, int *hour, int *minute); |
c0368918 GE |
90 | void split_daysec(int daysec, int *outhours=NULL, int *outminutes=NULL, int *outseconds=NULL); |
91 | std::string output_hour_minute(int hour, int minute, bool h_for_00=true, int seconds=0); | |
2c66f490 GE |
92 | |
93 | inline std::string output_hour_minute_from_seconds(int seconds) | |
94 | { | |
95 | int hour, minute; | |
c0368918 | 96 | split_daysec(seconds,&hour,&minute); |
2c66f490 GE |
97 | return output_hour_minute(hour,minute); |
98 | } | |
e93545dd | 99 | |
4e157d1d TJ |
100 | std::string get_month_name(unsigned char month); |
101 | ||
1b5dfd98 TJ |
102 | /** |
103 | * @brief structure representing a single (half-open) interval. | |
104 | */ | |
105 | class Interval | |
106 | { | |
107 | public: | |
108 | Interval() | |
109 | : m_lower_bound(0) | |
110 | , m_upper_bound(0) | |
80f30818 TJ |
111 | , m_weak_mark(0) |
112 | , m_changed(false) | |
1b5dfd98 TJ |
113 | { |
114 | } // | |
115 | ||
80f30818 | 116 | Interval( unsigned int start, unsigned int end, int weak_mark= 0 ) |
1b5dfd98 TJ |
117 | : m_lower_bound(start) |
118 | , m_upper_bound(end) | |
80f30818 TJ |
119 | , m_weak_mark(weak_mark) |
120 | , m_changed(false) | |
1b5dfd98 TJ |
121 | { |
122 | } // | |
123 | ||
d181c3bc TJ |
124 | |
125 | void clear(); | |
126 | ||
1b5dfd98 TJ |
127 | bool is_valid() const |
128 | { | |
129 | return m_lower_bound <= m_upper_bound; | |
130 | } // eo is_valid() const | |
131 | ||
132 | bool empty() const | |
133 | { | |
134 | return m_lower_bound == m_upper_bound; | |
135 | } // eo empty() const | |
136 | ||
137 | ||
138 | unsigned int lower_bound() const { return m_lower_bound; } | |
139 | unsigned int upper_bound() const { return m_upper_bound; } | |
140 | ||
80f30818 TJ |
141 | int weak_mark() const { return m_weak_mark; } |
142 | ||
143 | bool changed() const { return m_changed; } | |
144 | ||
1b5dfd98 TJ |
145 | |
146 | bool operator== (const Interval& other) const | |
147 | { | |
148 | return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound; | |
149 | } // eo operator==(const Interval&) | |
150 | ||
151 | ||
ebc3b584 TJ |
152 | bool operator!=(const Interval& other) const |
153 | { | |
154 | return not (*this == other); | |
155 | } // eo operator!=(const Interval&) | |
156 | ||
157 | ||
1b5dfd98 TJ |
158 | /** |
159 | * @brief less operator. compares only the start times! | |
160 | * @param other the other interval to compare with. | |
161 | * @return @a true if the current start is less than the other start. | |
162 | */ | |
163 | bool operator<(const Interval& other) const | |
164 | { | |
165 | return m_lower_bound < other.m_lower_bound; | |
166 | } // eo operator<(const Interval&) | |
167 | ||
168 | ||
169 | bool intersects(const Interval& other) const; | |
170 | bool contains(const Interval& other) const; | |
171 | ||
172 | ||
173 | protected: | |
174 | ||
175 | friend class Intervals; | |
176 | ||
177 | unsigned int m_lower_bound; | |
178 | unsigned int m_upper_bound; | |
179 | ||
80f30818 TJ |
180 | int m_weak_mark; |
181 | bool m_changed; | |
182 | ||
1b5dfd98 TJ |
183 | }; // eo Interval |
184 | ||
185 | ||
186 | ||
187 | /** | |
188 | * @brief structure representing a combination of single disjoint (half open) intervals. | |
189 | * | |
190 | * Basic idea is that this structure provides an interface for adding and | |
191 | * subtracting single intervals and keeps the internal list of intervals as | |
192 | * a list of disjoint intervals. | |
193 | * | |
194 | * @note the list is sorted by the start; lower comes first. | |
195 | * | |
196 | * @note the class provides some methods similar to STL container classes; | |
197 | * i.e. it can be used with (at least some) STL algorithms. | |
198 | * | |
199 | * @internal | |
200 | * we use a std::list for the intervals; this means we don't invalidate all | |
201 | * iterators when we insert or delete within loops... | |
202 | * And we use that fact!! | |
203 | */ | |
204 | class Intervals | |
205 | { | |
206 | public: | |
207 | typedef std::list< Interval > IntervalList; | |
208 | typedef IntervalList::value_type value_type; | |
209 | typedef IntervalList::const_iterator const_iterator; | |
210 | typedef IntervalList::const_iterator iterator; // we allow only const... | |
211 | typedef IntervalList::size_type size_type; | |
212 | ||
213 | public: | |
214 | Intervals(); | |
215 | ||
216 | void add(const Interval& new_frame); | |
217 | void sub(const Interval& new_frame); | |
218 | ||
d181c3bc | 219 | void clear(); |
1b5dfd98 TJ |
220 | |
221 | const_iterator begin() const { return m_intervals.begin(); } | |
222 | const_iterator end() const { return m_intervals.end(); } | |
223 | ||
224 | bool empty() const { return m_intervals.empty(); } | |
225 | const Interval& front() const { return m_intervals.front(); } | |
226 | const Interval& back() const { return m_intervals.back(); } | |
227 | ||
228 | size_type size() const { return m_intervals.size(); } | |
229 | ||
230 | bool intersects(const Interval& other) const; | |
231 | bool intersects(const Intervals& other) const; | |
232 | ||
233 | bool contains(const Interval& other) const; | |
234 | bool contains(const Intervals& other) const; | |
235 | ||
e156de7c TJ |
236 | bool contains_exact(const Interval& other) const; |
237 | ||
1b5dfd98 | 238 | bool operator==(const Intervals& other) const; |
ebc3b584 | 239 | bool operator!=(const Intervals& other) const { return not (*this == other) ; } |
1b5dfd98 TJ |
240 | |
241 | Intervals& operator+=(const Interval& other); | |
242 | Intervals& operator-=(const Interval& other); | |
243 | ||
244 | Intervals& operator+=(const Intervals& other); | |
245 | Intervals& operator-=(const Intervals& other); | |
246 | ||
247 | protected: | |
248 | ||
249 | std::list< Interval > m_intervals; | |
250 | ||
251 | }; // eo Intervals | |
252 | ||
253 | ||
96d0be2e TJ |
254 | /* |
255 | ** clock funcs: | |
256 | */ | |
257 | ||
258 | ||
259 | bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds); | |
b7e17426 | 260 | long long monotonic_clock_gettime_nano(); |
96d0be2e TJ |
261 | |
262 | bool realtime_clock_gettime(long int& seconds, long int& nano_seconds); | |
263 | ||
8b5814e2 PG |
264 | namespace I2n { |
265 | ||
266 | namespace clock { | |
267 | ||
cf960f73 PG |
268 | class conversion_error : public std::exception |
269 | { | |
270 | public: | |
271 | const int err; | |
272 | const std::string context; | |
273 | ||
274 | conversion_error (const int err, const std::string &context) | |
275 | : err (err) | |
276 | , context (context) | |
277 | { } | |
278 | ||
279 | virtual ~conversion_error (void) throw() { }; | |
280 | ||
281 | operator std::string (void) | |
282 | { | |
283 | return std::string ("errno=") + I2n::to_string (this->err) | |
284 | + " [" + this->context + "]"; | |
285 | } | |
286 | }; | |
287 | ||
e36ca33c PG |
288 | namespace { |
289 | ||
290 | /* helper for ctor initializer list; we still lack aggregate initializers */ | |
291 | struct timespec | |
292 | timespec_of_parts (const time_t sec, const long nsec) | |
293 | { | |
294 | struct timespec ret = { sec, nsec}; | |
295 | ||
296 | return ret; | |
297 | } | |
298 | ||
299 | } /* [namespace] */ | |
300 | ||
8b5814e2 PG |
301 | namespace type { |
302 | /* | |
303 | * represent the clock id options from clock_gettime(2) as | |
304 | * a pair of enums. by default, CLOCK_MONOTONIC_COARSE is used | |
305 | * everywhere since that’s what we want in most cases. | |
306 | */ | |
307 | enum id { | |
308 | mono, /* CLOCK_MONOTONIC_COARSE */ | |
309 | real, /* CLOCK_REALIME_COARSE */ | |
310 | boot, /* CLOCK_BOOTTIME */ | |
311 | cpu, /* CLOCK_CPUTIME_* */ | |
312 | }; | |
313 | ||
314 | /* | |
315 | * for clocks that support it: non-coarse or raw variants; if a variant | |
316 | * does not apply to a given clock, it is ignored | |
317 | */ | |
318 | enum variant { | |
319 | dflt, /* all */ | |
320 | exact, /* mono, real: not (*_COARSE) */ | |
321 | raw, /* mono: _RAW */ | |
322 | process, /* cpu: *_PROCESS_* */ | |
323 | thread, /* cpu: *_THREAD_* */ | |
324 | }; | |
325 | ||
326 | } /* [namespace type] */ | |
327 | ||
328 | ||
329 | class Time { | |
330 | ||
331 | private: | |
e36ca33c | 332 | struct timespec value; |
8b5814e2 PG |
333 | |
334 | public: | |
e36ca33c PG |
335 | enum type::id id; |
336 | enum type::variant variant; | |
337 | int err; | |
338 | ||
339 | private: | |
340 | /* | |
341 | * Handle decimal part (nanosecond) overflow; this is performed | |
342 | * after arithmetic operations and whenever we there is the | |
343 | * possibility of unsanitized input for example in constructors | |
344 | * from other types and suchlike. | |
345 | * | |
346 | * POSIX defines the ns part as *long*. Technically, that means | |
347 | * that on machines where *sizeof long* equals *sizeof int*, it can | |
fe377737 | 348 | * represent only up to around 2.1 seconds. In this range, the loop |
e36ca33c PG |
349 | * version is most likely faster than division. However, since in |
350 | * practice *long* is 8 bytes just about anywhere, we have to | |
351 | * handle greater dividends first. | |
352 | */ | |
353 | inline void | |
354 | carry_nsec (void) | |
355 | { | |
356 | # if LONG_BIT > 32 | |
357 | if ( this->value.tv_nsec < -3L * TIME_CONST_FACTOR_NANO | |
358 | || this->value.tv_nsec > 3L * TIME_CONST_FACTOR_NANO) | |
359 | { | |
360 | const long sec = this->value.tv_nsec / TIME_CONST_FACTOR_NANO; | |
361 | this->value.tv_nsec -= sec * TIME_CONST_FACTOR_NANO; | |
362 | this->value.tv_sec += sec; | |
363 | } | |
364 | # endif /* [LONG_BIT > 32] */ | |
365 | while (this->value.tv_nsec >= TIME_CONST_FACTOR_NANO) { | |
366 | this->value.tv_sec += 1; | |
367 | this->value.tv_nsec -= TIME_CONST_FACTOR_NANO; | |
368 | } | |
369 | ||
370 | while (this->value.tv_nsec < 0) { | |
371 | this->value.tv_sec -= 1; | |
372 | this->value.tv_nsec += TIME_CONST_FACTOR_NANO; | |
373 | } | |
374 | } | |
8b5814e2 PG |
375 | |
376 | /* ctors *************************************************************/ | |
377 | public: | |
378 | ||
379 | Time (const enum type::id id = type::mono, | |
e36ca33c PG |
380 | const enum type::variant var = type::dflt) NOEXCEPT; |
381 | ||
382 | inline Time (const Time &t) NOEXCEPT | |
383 | : value (t.value) | |
384 | , id (t.id) | |
385 | , variant (t.variant) | |
386 | , err (t.err) | |
387 | { } | |
388 | ||
cf960f73 PG |
389 | inline |
390 | Time (const time_t sec, | |
391 | const long nsec = 0, | |
392 | const enum type::id id = type::mono, | |
393 | const enum type::variant var = type::dflt, | |
394 | const int err = 0) NOEXCEPT | |
e36ca33c PG |
395 | : value (timespec_of_parts (sec, nsec)) |
396 | , id (id) | |
397 | , variant (var) | |
398 | , err (err) | |
399 | { this->carry_nsec (); } | |
400 | ||
cf960f73 | 401 | explicit |
2795e39c PG |
402 | Time (const struct tm &tm, |
403 | const enum type::id id = type::mono, | |
cf960f73 | 404 | const enum type::variant var = type::dflt); |
2795e39c | 405 | |
e36ca33c | 406 | /* value read access *************************************************/ |
8b5814e2 PG |
407 | public: |
408 | ||
e36ca33c | 409 | inline CONSTEXPR const struct timespec &get_time (void) const NOEXCEPT |
8b5814e2 PG |
410 | { return this->value; } |
411 | ||
e36ca33c PG |
412 | inline CONSTEXPR const time_t &get_sec (void) const NOEXCEPT |
413 | { return this->value.tv_sec; } | |
8b5814e2 | 414 | |
e36ca33c | 415 | inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT |
8b5814e2 PG |
416 | { return this->value.tv_nsec; } |
417 | ||
9f39641d PG |
418 | inline CONSTEXPR const long get_msec (void) const NOEXCEPT |
419 | { return this->get_nsec () / 1000000; } | |
420 | ||
e36ca33c | 421 | int64_t as_nanosec (void) const NOEXCEPT; |
8b5814e2 | 422 | |
e36ca33c | 423 | long as_nanosec_L (void) const NOEXCEPT; |
8b5814e2 | 424 | |
e36ca33c | 425 | /* value write access ************************************************/ |
8b5814e2 PG |
426 | public: |
427 | ||
428 | inline void | |
e36ca33c PG |
429 | swap (Time &t) NOEXCEPT |
430 | { | |
431 | std::swap (this->value , t.value ); | |
432 | std::swap (this->id , t.id ); | |
433 | std::swap (this->variant, t.variant); | |
434 | std::swap (this->err , t.err ); | |
435 | } | |
436 | ||
437 | Time &operator= (Time t) NOEXCEPT; | |
438 | ||
439 | Time &operator= (struct timespec ts) NOEXCEPT; | |
8b5814e2 PG |
440 | |
441 | inline void | |
e36ca33c PG |
442 | set (const struct timespec &ts) NOEXCEPT |
443 | { | |
444 | this->value = ts; | |
445 | this->carry_nsec (); | |
446 | } | |
447 | ||
448 | inline void | |
449 | set (const time_t sec, | |
450 | const long nsec, | |
451 | const enum type::id id = type::mono, | |
452 | const enum type::variant var = type::dflt) NOEXCEPT | |
8b5814e2 PG |
453 | { |
454 | this->value.tv_sec = sec; | |
455 | this->value.tv_nsec = nsec; | |
e36ca33c PG |
456 | this->id = id; |
457 | this->variant = var; | |
458 | ||
459 | this->carry_nsec (); | |
460 | } | |
8b5814e2 | 461 | |
e36ca33c PG |
462 | bool set (void) NOEXCEPT; |
463 | ||
464 | void unset (void) NOEXCEPT; | |
465 | ||
466 | /* arithmetic ********************************************************/ | |
467 | public: | |
8b5814e2 | 468 | |
e36ca33c PG |
469 | Time &add (const time_t sec, const long nsec) NOEXCEPT; |
470 | ||
471 | Time &subtract (const time_t sec, const long nsec) NOEXCEPT; | |
472 | ||
473 | inline Time &add (const Time &t2) NOEXCEPT | |
474 | { return this->add (t2.value.tv_sec, t2.value.tv_nsec); } | |
475 | ||
476 | inline Time &add (const time_t t2) NOEXCEPT | |
477 | { return this->add (t2, 0L); }; | |
478 | ||
479 | inline Time &subtract (const Time &t2) NOEXCEPT | |
480 | { return this->subtract (t2.value.tv_sec, t2.value.tv_nsec); } | |
481 | ||
482 | inline Time &subtract (const time_t t2) NOEXCEPT | |
483 | { return this->subtract (t2, 0L); }; | |
484 | ||
c42fd3b3 PG |
485 | Time &scale (const int64_t factor) NOEXCEPT; |
486 | ||
487 | Time ÷ (const int64_t divisor) NOEXCEPT; | |
e36ca33c PG |
488 | |
489 | friend int compare (const Time &t1, const Time &t2) NOEXCEPT; | |
490 | ||
491 | inline Time | |
492 | difference (const Time &t) NOEXCEPT | |
493 | { return (*this < t) ? t - *this : *this - t; } | |
494 | ||
495 | /* overloads *********************************************************/ | |
496 | public: | |
497 | ||
498 | inline Time | |
499 | operator+ (const Time &t2) const NOEXCEPT | |
500 | { return Time (*this).add (t2); } | |
501 | ||
502 | inline Time | |
503 | operator+ (const time_t t2) const NOEXCEPT | |
504 | { return Time (*this).add (t2); } | |
505 | ||
506 | inline Time & | |
507 | operator+= (const Time &t2) NOEXCEPT | |
508 | { return this->add (t2); } | |
509 | ||
510 | inline Time & | |
511 | operator+= (const time_t t2) NOEXCEPT | |
512 | { return this->add (t2); } | |
513 | ||
514 | inline Time | |
515 | operator- (const Time &t2) const NOEXCEPT | |
516 | { return Time (*this).subtract (t2); } | |
517 | ||
518 | inline Time | |
519 | operator- (const time_t t2) const NOEXCEPT | |
520 | { return Time (*this).subtract (t2); } | |
521 | ||
522 | inline Time & | |
523 | operator-= (const Time &t2) NOEXCEPT | |
524 | { return this->subtract (t2); } | |
525 | ||
526 | inline Time & | |
527 | operator-= (const time_t t2) NOEXCEPT | |
528 | { return this->subtract (t2); } | |
529 | ||
530 | inline Time | |
c42fd3b3 | 531 | operator* (const int64_t factor) const NOEXCEPT |
e36ca33c PG |
532 | { return Time (*this).scale (factor); } |
533 | ||
534 | inline Time & | |
c42fd3b3 | 535 | operator*= (const int64_t factor) NOEXCEPT |
e36ca33c PG |
536 | { return this->scale (factor); } |
537 | ||
c42fd3b3 PG |
538 | inline Time |
539 | operator/ (const int64_t divisor) const NOEXCEPT | |
540 | { return Time (*this).divide (divisor); } | |
541 | ||
542 | inline Time & | |
543 | operator/= (const int64_t divisor) NOEXCEPT | |
544 | { return this->divide (divisor); } | |
545 | ||
e36ca33c PG |
546 | friend CONSTEXPR bool |
547 | operator== (const Time &t1, const Time &t2) NOEXCEPT; | |
548 | ||
549 | friend CONSTEXPR bool | |
550 | operator< (const Time &t1, const Time &t2) NOEXCEPT; | |
551 | ||
552 | friend CONSTEXPR bool | |
553 | operator> (const Time &t1, const Time &t2) NOEXCEPT; | |
554 | ||
555 | friend std::ostream & | |
556 | operator<< (std::ostream &os, const Time &t); | |
8b5814e2 | 557 | |
72acd54c PG |
558 | /* formatting ********************************************************/ |
559 | public: | |
560 | ||
561 | boost::optional<std::string> | |
562 | format_iso8601 (const bool utc = true, | |
563 | const bool date = true, | |
564 | const bool time = true, | |
565 | const bool tz = true) const; | |
566 | ||
9f39641d PG |
567 | std::string make_nice_time (void) const; |
568 | std::string format_full_time (void) const; | |
569 | std::string format_date (void) const; | |
570 | ||
571 | inline std::string | |
572 | format_sec_msec (void) const | |
573 | { return ::format_sec_msec (this->value); } | |
574 | ||
575 | inline boost::optional<std::string> | |
576 | format_min_sec_msec (void) const | |
577 | { return ::format_min_sec_msec (this->value); } | |
72acd54c | 578 | |
8b5814e2 PG |
579 | }; /* [class Time] */ |
580 | ||
e36ca33c PG |
581 | inline Time |
582 | operator+ (const time_t t1, const Time &t2) NOEXCEPT | |
583 | { return Time (t1) + t2; } | |
584 | ||
585 | inline Time | |
586 | operator- (const time_t t1, const Time &t2) NOEXCEPT | |
587 | { return Time (t1) - t2; } | |
588 | ||
c42fd3b3 PG |
589 | inline Time |
590 | operator* (const time_t t1, const Time &t2) NOEXCEPT | |
591 | { return t2 * t1; } | |
592 | ||
e36ca33c PG |
593 | int compare (const Time &t1, const Time &t2) NOEXCEPT; |
594 | ||
595 | /* | |
596 | * comparison for equality also considers the clock type; | |
597 | */ | |
598 | inline CONSTEXPR bool | |
599 | operator== (const Time &t1, const Time &t2) NOEXCEPT | |
600 | { | |
601 | return t1.id == t2.id && t1.variant == t2.variant | |
602 | && t1.value.tv_sec == t2.value.tv_sec | |
603 | && t1.value.tv_nsec == t2.value.tv_nsec | |
604 | ; | |
605 | } | |
606 | ||
607 | /* these ignore the *id* and *variant* fields */ | |
608 | inline CONSTEXPR bool | |
609 | operator< (const Time &t1, const Time &t2) NOEXCEPT | |
610 | { | |
611 | return t1.value.tv_sec < t2.value.tv_sec | |
612 | || ( t1.value.tv_sec == t2.value.tv_sec | |
613 | && t1.value.tv_nsec < t2.value.tv_nsec) | |
614 | ; | |
615 | } | |
616 | ||
617 | /* these ignore the *id* and *variant* fields */ | |
618 | inline CONSTEXPR bool | |
619 | operator> (const Time &t1, const Time &t2) NOEXCEPT | |
620 | { | |
621 | return t1.value.tv_sec > t2.value.tv_sec | |
622 | || ( t1.value.tv_sec == t2.value.tv_sec | |
623 | && t1.value.tv_nsec > t2.value.tv_nsec) | |
624 | ; | |
625 | } | |
626 | ||
627 | inline std::ostream & | |
628 | operator<< (std::ostream &os, const Time &t) | |
629 | { | |
f8ebfa53 | 630 | os << I2n::to_string (t.value.tv_sec) << "s, " |
e36ca33c PG |
631 | << I2n::to_string (t.value.tv_nsec) << "ns" |
632 | ; | |
633 | ||
634 | return os; | |
635 | } | |
636 | ||
8b5814e2 PG |
637 | boost::optional<Time> |
638 | now (const enum type::id id = type::mono, | |
e36ca33c PG |
639 | const enum type::variant var = type::dflt) NOEXCEPT; |
640 | ||
641 | Time | |
642 | zero (const enum type::id id = type::mono, | |
643 | const enum type::variant var = type::dflt) NOEXCEPT; | |
8b5814e2 | 644 | |
2795e39c PG |
645 | boost::optional<Time> |
646 | time_of_iso8601 (const std::string &s, | |
647 | const bool date = true, | |
648 | const bool time = true, | |
649 | const bool tz = true, | |
650 | const enum type::id id = type::real, | |
651 | const enum type::variant var = type::dflt) NOEXCEPT; | |
652 | ||
c42fd3b3 PG |
653 | template <typename ContT> |
654 | Time | |
655 | mean (const ContT &data) | |
656 | { | |
657 | Time sum (0, 0); | |
658 | ||
659 | if (data.size () == 0) { | |
660 | return sum; | |
661 | } | |
662 | ||
663 | for (typename ContT::const_iterator it = data.begin (); | |
664 | it != data.end (); ++it) | |
665 | { | |
666 | sum += *it; | |
667 | }; | |
668 | ||
669 | return sum.divide (static_cast<int64_t> (data.size ())); | |
670 | }; | |
671 | ||
672 | template <typename ContT> | |
673 | Time | |
674 | median (const ContT &data) | |
675 | { | |
676 | if (data.size () == 0) { | |
677 | return zero (); | |
678 | } | |
679 | if (data.size () == 1) { | |
680 | return *data.begin (); | |
681 | } | |
682 | ||
683 | std::vector<typename ContT::value_type> sorted; | |
684 | std::copy (data.begin (), data.end (), std::back_inserter (sorted)); | |
685 | std::sort (sorted.begin (), sorted.end ()); | |
686 | ||
687 | return sorted [data.size () / 2]; | |
688 | }; | |
689 | ||
8b5814e2 PG |
690 | } /* [namespace clock] */ |
691 | ||
692 | } /* [namespace I2n] */ | |
1b5dfd98 TJ |
693 | |
694 | ||
e93545dd | 695 | #endif |