2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
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.
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.
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.
21 * @brief time related functions.
23 * @copyright Copyright © 2001-2018 by Intra2net AG
26 #ifndef __TIMEFUNC_HXX
27 #define __TIMEFUNC_HXX
35 #include <boost/optional.hpp>
39 #include "stringfunc.hxx"
41 #if __cplusplus >= 201103
42 # define CONSTEXPR constexpr
43 # define NOEXCEPT noexcept
49 #define TIME_CONST_FACTOR_NANO (1000L * 1000 * 1000)
51 double prec_time(void);
53 time_t date_to_seconds(const std::string &date);
55 std::string make_nice_time(int seconds);
56 std::string format_full_time(time_t seconds);
57 std::string format_date(time_t seconds);
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,
63 inline std::string format_iso8601(const struct timespec ts, const bool utc=true,
64 const bool date=true, const bool time=true,
66 { return format_iso8601 (ts.tv_sec, utc, date, time, tz); }
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,
74 const bool tz=true) NOEXCEPT
75 { return scan_iso8601 (s.c_str (), date, time, tz); }
78 void seconds_to_hour_minute(int seconds, int *hour, int *minute);
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);
82 inline std::string output_hour_minute_from_seconds(int seconds)
85 split_daysec(seconds,&hour,&minute);
86 return output_hour_minute(hour,minute);
89 std::string get_month_name(unsigned char month);
92 * @brief structure representing a single (half-open) interval.
105 Interval( unsigned int start, unsigned int end, int weak_mark= 0 )
106 : m_lower_bound(start)
108 , m_weak_mark(weak_mark)
116 bool is_valid() const
118 return m_lower_bound <= m_upper_bound;
119 } // eo is_valid() const
123 return m_lower_bound == m_upper_bound;
124 } // eo empty() const
127 unsigned int lower_bound() const { return m_lower_bound; }
128 unsigned int upper_bound() const { return m_upper_bound; }
130 int weak_mark() const { return m_weak_mark; }
132 bool changed() const { return m_changed; }
135 bool operator== (const Interval& other) const
137 return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound;
138 } // eo operator==(const Interval&)
141 bool operator!=(const Interval& other) const
143 return not (*this == other);
144 } // eo operator!=(const Interval&)
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.
152 bool operator<(const Interval& other) const
154 return m_lower_bound < other.m_lower_bound;
155 } // eo operator<(const Interval&)
158 bool intersects(const Interval& other) const;
159 bool contains(const Interval& other) const;
164 friend class Intervals;
166 unsigned int m_lower_bound;
167 unsigned int m_upper_bound;
177 * @brief structure representing a combination of single disjoint (half open) intervals.
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.
183 * @note the list is sorted by the start; lower comes first.
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.
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!!
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;
205 void add(const Interval& new_frame);
206 void sub(const Interval& new_frame);
210 const_iterator begin() const { return m_intervals.begin(); }
211 const_iterator end() const { return m_intervals.end(); }
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(); }
217 size_type size() const { return m_intervals.size(); }
219 bool intersects(const Interval& other) const;
220 bool intersects(const Intervals& other) const;
222 bool contains(const Interval& other) const;
223 bool contains(const Intervals& other) const;
225 bool contains_exact(const Interval& other) const;
227 bool operator==(const Intervals& other) const;
228 bool operator!=(const Intervals& other) const { return not (*this == other) ; }
230 Intervals& operator+=(const Interval& other);
231 Intervals& operator-=(const Interval& other);
233 Intervals& operator+=(const Intervals& other);
234 Intervals& operator-=(const Intervals& other);
238 std::list< Interval > m_intervals;
248 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds);
249 long long monotonic_clock_gettime_nano();
251 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds);
259 /* helper for ctor initializer list; we still lack aggregate initializers */
261 timespec_of_parts (const time_t sec, const long nsec)
263 struct timespec ret = { sec, nsec};
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.
277 mono, /* CLOCK_MONOTONIC_COARSE */
278 real, /* CLOCK_REALIME_COARSE */
279 boot, /* CLOCK_BOOTTIME */
280 cpu, /* CLOCK_CPUTIME_* */
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
289 exact, /* mono, real: not (*_COARSE) */
290 raw, /* mono: _RAW */
291 process, /* cpu: *_PROCESS_* */
292 thread, /* cpu: *_THREAD_* */
295 } /* [namespace type] */
301 struct timespec value;
305 enum type::variant variant;
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.
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.
326 if ( this->value.tv_nsec < -3L * TIME_CONST_FACTOR_NANO
327 || this->value.tv_nsec > 3L * TIME_CONST_FACTOR_NANO)
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;
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;
339 while (this->value.tv_nsec < 0) {
340 this->value.tv_sec -= 1;
341 this->value.tv_nsec += TIME_CONST_FACTOR_NANO;
345 /* ctors *************************************************************/
348 Time (const enum type::id id = type::mono,
349 const enum type::variant var = type::dflt) NOEXCEPT;
351 inline Time (const Time &t) NOEXCEPT
354 , variant (t.variant)
358 inline Time (const time_t sec,
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))
367 { this->carry_nsec (); }
369 Time (const struct tm &tm,
370 const enum type::id id = type::mono,
371 const enum type::variant var = type::dflt) NOEXCEPT;
373 /* value read access *************************************************/
376 inline CONSTEXPR const struct timespec &get_time (void) const NOEXCEPT
377 { return this->value; }
379 inline CONSTEXPR const time_t &get_sec (void) const NOEXCEPT
380 { return this->value.tv_sec; }
382 inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT
383 { return this->value.tv_nsec; }
385 int64_t as_nanosec (void) const NOEXCEPT;
387 long as_nanosec_L (void) const NOEXCEPT;
389 /* value write access ************************************************/
393 swap (Time &t) NOEXCEPT
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 );
401 Time &operator= (Time t) NOEXCEPT;
403 Time &operator= (struct timespec ts) NOEXCEPT;
406 set (const struct timespec &ts) NOEXCEPT
413 set (const time_t sec,
415 const enum type::id id = type::mono,
416 const enum type::variant var = type::dflt) NOEXCEPT
418 this->value.tv_sec = sec;
419 this->value.tv_nsec = nsec;
426 bool set (void) NOEXCEPT;
428 void unset (void) NOEXCEPT;
430 /* arithmetic ********************************************************/
433 Time &add (const time_t sec, const long nsec) NOEXCEPT;
435 Time &subtract (const time_t sec, const long nsec) NOEXCEPT;
437 inline Time &add (const Time &t2) NOEXCEPT
438 { return this->add (t2.value.tv_sec, t2.value.tv_nsec); }
440 inline Time &add (const time_t t2) NOEXCEPT
441 { return this->add (t2, 0L); };
443 inline Time &subtract (const Time &t2) NOEXCEPT
444 { return this->subtract (t2.value.tv_sec, t2.value.tv_nsec); }
446 inline Time &subtract (const time_t t2) NOEXCEPT
447 { return this->subtract (t2, 0L); };
449 Time &scale (const int64_t factor) NOEXCEPT;
451 Time ÷ (const int64_t divisor) NOEXCEPT;
453 friend int compare (const Time &t1, const Time &t2) NOEXCEPT;
456 difference (const Time &t) NOEXCEPT
457 { return (*this < t) ? t - *this : *this - t; }
459 /* overloads *********************************************************/
463 operator+ (const Time &t2) const NOEXCEPT
464 { return Time (*this).add (t2); }
467 operator+ (const time_t t2) const NOEXCEPT
468 { return Time (*this).add (t2); }
471 operator+= (const Time &t2) NOEXCEPT
472 { return this->add (t2); }
475 operator+= (const time_t t2) NOEXCEPT
476 { return this->add (t2); }
479 operator- (const Time &t2) const NOEXCEPT
480 { return Time (*this).subtract (t2); }
483 operator- (const time_t t2) const NOEXCEPT
484 { return Time (*this).subtract (t2); }
487 operator-= (const Time &t2) NOEXCEPT
488 { return this->subtract (t2); }
491 operator-= (const time_t t2) NOEXCEPT
492 { return this->subtract (t2); }
495 operator* (const int64_t factor) const NOEXCEPT
496 { return Time (*this).scale (factor); }
499 operator*= (const int64_t factor) NOEXCEPT
500 { return this->scale (factor); }
503 operator/ (const int64_t divisor) const NOEXCEPT
504 { return Time (*this).divide (divisor); }
507 operator/= (const int64_t divisor) NOEXCEPT
508 { return this->divide (divisor); }
510 friend CONSTEXPR bool
511 operator== (const Time &t1, const Time &t2) NOEXCEPT;
513 friend CONSTEXPR bool
514 operator< (const Time &t1, const Time &t2) NOEXCEPT;
516 friend CONSTEXPR bool
517 operator> (const Time &t1, const Time &t2) NOEXCEPT;
519 friend std::ostream &
520 operator<< (std::ostream &os, const Time &t);
522 /* formatting ********************************************************/
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;
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;
535 }; /* [class Time] */
538 operator+ (const time_t t1, const Time &t2) NOEXCEPT
539 { return Time (t1) + t2; }
542 operator- (const time_t t1, const Time &t2) NOEXCEPT
543 { return Time (t1) - t2; }
546 operator* (const time_t t1, const Time &t2) NOEXCEPT
549 int compare (const Time &t1, const Time &t2) NOEXCEPT;
552 * comparison for equality also considers the clock type;
554 inline CONSTEXPR bool
555 operator== (const Time &t1, const Time &t2) NOEXCEPT
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
563 /* these ignore the *id* and *variant* fields */
564 inline CONSTEXPR bool
565 operator< (const Time &t1, const Time &t2) NOEXCEPT
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)
573 /* these ignore the *id* and *variant* fields */
574 inline CONSTEXPR bool
575 operator> (const Time &t1, const Time &t2) NOEXCEPT
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)
583 inline std::ostream &
584 operator<< (std::ostream &os, const Time &t)
586 os << I2n::to_string (t.value.tv_sec) << "ms, "
587 << I2n::to_string (t.value.tv_nsec) << "ns"
593 boost::optional<Time>
594 now (const enum type::id id = type::mono,
595 const enum type::variant var = type::dflt) NOEXCEPT;
598 zero (const enum type::id id = type::mono,
599 const enum type::variant var = type::dflt) NOEXCEPT;
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;
609 template <typename ContT>
611 mean (const ContT &data)
615 if (data.size () == 0) {
619 for (typename ContT::const_iterator it = data.begin ();
620 it != data.end (); ++it)
625 return sum.divide (static_cast<int64_t> (data.size ()));
628 template <typename ContT>
630 median (const ContT &data)
632 if (data.size () == 0) {
635 if (data.size () == 1) {
636 return *data.begin ();
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 ());
643 return sorted [data.size () / 2];
646 } /* [namespace clock] */
648 } /* [namespace I2n] */