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