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