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-2008 by Intra2net AG
26 #ifndef __TIMEFUNC_HXX
27 #define __TIMEFUNC_HXX
34 #include <boost/optional.hpp>
38 #include "stringfunc.hxx"
40 #if __cplusplus >= 201103
41 # define CONSTEXPR constexpr
42 # define NOEXCEPT noexcept
48 #define TIME_CONST_FACTOR_NANO (1000L * 1000 * 1000)
50 double prec_time(void);
52 time_t date_to_seconds(const std::string &date);
54 std::string make_nice_time(int seconds);
55 std::string format_full_time(time_t seconds);
56 std::string format_date(time_t seconds);
57 void seconds_to_hour_minute(int seconds, int *hour, int *minute);
58 void split_daysec(int daysec, int *outhours=NULL, int *outminutes=NULL, int *outseconds=NULL);
59 std::string output_hour_minute(int hour, int minute, bool h_for_00=true, int seconds=0);
61 inline std::string output_hour_minute_from_seconds(int seconds)
64 split_daysec(seconds,&hour,&minute);
65 return output_hour_minute(hour,minute);
68 std::string get_month_name(unsigned char month);
71 * @brief structure representing a single (half-open) interval.
84 Interval( unsigned int start, unsigned int end, int weak_mark= 0 )
85 : m_lower_bound(start)
87 , m_weak_mark(weak_mark)
97 return m_lower_bound <= m_upper_bound;
98 } // eo is_valid() const
102 return m_lower_bound == m_upper_bound;
103 } // eo empty() const
106 unsigned int lower_bound() const { return m_lower_bound; }
107 unsigned int upper_bound() const { return m_upper_bound; }
109 int weak_mark() const { return m_weak_mark; }
111 bool changed() const { return m_changed; }
114 bool operator== (const Interval& other) const
116 return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound;
117 } // eo operator==(const Interval&)
120 bool operator!=(const Interval& other) const
122 return not (*this == other);
123 } // eo operator!=(const Interval&)
127 * @brief less operator. compares only the start times!
128 * @param other the other interval to compare with.
129 * @return @a true if the current start is less than the other start.
131 bool operator<(const Interval& other) const
133 return m_lower_bound < other.m_lower_bound;
134 } // eo operator<(const Interval&)
137 bool intersects(const Interval& other) const;
138 bool contains(const Interval& other) const;
143 friend class Intervals;
145 unsigned int m_lower_bound;
146 unsigned int m_upper_bound;
156 * @brief structure representing a combination of single disjoint (half open) intervals.
158 * Basic idea is that this structure provides an interface for adding and
159 * subtracting single intervals and keeps the internal list of intervals as
160 * a list of disjoint intervals.
162 * @note the list is sorted by the start; lower comes first.
164 * @note the class provides some methods similar to STL container classes;
165 * i.e. it can be used with (at least some) STL algorithms.
168 * we use a std::list for the intervals; this means we don't invalidate all
169 * iterators when we insert or delete within loops...
170 * And we use that fact!!
175 typedef std::list< Interval > IntervalList;
176 typedef IntervalList::value_type value_type;
177 typedef IntervalList::const_iterator const_iterator;
178 typedef IntervalList::const_iterator iterator; // we allow only const...
179 typedef IntervalList::size_type size_type;
184 void add(const Interval& new_frame);
185 void sub(const Interval& new_frame);
189 const_iterator begin() const { return m_intervals.begin(); }
190 const_iterator end() const { return m_intervals.end(); }
192 bool empty() const { return m_intervals.empty(); }
193 const Interval& front() const { return m_intervals.front(); }
194 const Interval& back() const { return m_intervals.back(); }
196 size_type size() const { return m_intervals.size(); }
198 bool intersects(const Interval& other) const;
199 bool intersects(const Intervals& other) const;
201 bool contains(const Interval& other) const;
202 bool contains(const Intervals& other) const;
204 bool contains_exact(const Interval& other) const;
206 bool operator==(const Intervals& other) const;
207 bool operator!=(const Intervals& other) const { return not (*this == other) ; }
209 Intervals& operator+=(const Interval& other);
210 Intervals& operator-=(const Interval& other);
212 Intervals& operator+=(const Intervals& other);
213 Intervals& operator-=(const Intervals& other);
217 std::list< Interval > m_intervals;
227 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds);
228 long long monotonic_clock_gettime_nano();
230 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds);
238 /* helper for ctor initializer list; we still lack aggregate initializers */
240 timespec_of_parts (const time_t sec, const long nsec)
242 struct timespec ret = { sec, nsec};
251 * represent the clock id options from clock_gettime(2) as
252 * a pair of enums. by default, CLOCK_MONOTONIC_COARSE is used
253 * everywhere since that’s what we want in most cases.
256 mono, /* CLOCK_MONOTONIC_COARSE */
257 real, /* CLOCK_REALIME_COARSE */
258 boot, /* CLOCK_BOOTTIME */
259 cpu, /* CLOCK_CPUTIME_* */
263 * for clocks that support it: non-coarse or raw variants; if a variant
264 * does not apply to a given clock, it is ignored
268 exact, /* mono, real: not (*_COARSE) */
269 raw, /* mono: _RAW */
270 process, /* cpu: *_PROCESS_* */
271 thread, /* cpu: *_THREAD_* */
274 } /* [namespace type] */
280 struct timespec value;
284 enum type::variant variant;
289 * Handle decimal part (nanosecond) overflow; this is performed
290 * after arithmetic operations and whenever we there is the
291 * possibility of unsanitized input for example in constructors
292 * from other types and suchlike.
294 * POSIX defines the ns part as *long*. Technically, that means
295 * that on machines where *sizeof long* equals *sizeof int*, it can
296 * represent only up to arund 2.1 seconds. In this range, the loop
297 * version is most likely faster than division. However, since in
298 * practice *long* is 8 bytes just about anywhere, we have to
299 * handle greater dividends first.
305 if ( this->value.tv_nsec < -3L * TIME_CONST_FACTOR_NANO
306 || this->value.tv_nsec > 3L * TIME_CONST_FACTOR_NANO)
308 const long sec = this->value.tv_nsec / TIME_CONST_FACTOR_NANO;
309 this->value.tv_nsec -= sec * TIME_CONST_FACTOR_NANO;
310 this->value.tv_sec += sec;
312 # endif /* [LONG_BIT > 32] */
313 while (this->value.tv_nsec >= TIME_CONST_FACTOR_NANO) {
314 this->value.tv_sec += 1;
315 this->value.tv_nsec -= TIME_CONST_FACTOR_NANO;
318 while (this->value.tv_nsec < 0) {
319 this->value.tv_sec -= 1;
320 this->value.tv_nsec += TIME_CONST_FACTOR_NANO;
324 /* ctors *************************************************************/
327 Time (const enum type::id id = type::mono,
328 const enum type::variant var = type::dflt) NOEXCEPT;
330 inline Time (const Time &t) NOEXCEPT
333 , variant (t.variant)
337 inline Time (const time_t sec,
339 const enum type::id id = type::mono,
340 const enum type::variant var = type::dflt,
341 const int err = 0) NOEXCEPT
342 : value (timespec_of_parts (sec, nsec))
346 { this->carry_nsec (); }
348 /* value read access *************************************************/
351 inline CONSTEXPR const struct timespec &get_time (void) const NOEXCEPT
352 { return this->value; }
354 inline CONSTEXPR const time_t &get_sec (void) const NOEXCEPT
355 { return this->value.tv_sec; }
357 inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT
358 { return this->value.tv_nsec; }
360 int64_t as_nanosec (void) const NOEXCEPT;
362 long as_nanosec_L (void) const NOEXCEPT;
364 /* value write access ************************************************/
368 swap (Time &t) NOEXCEPT
370 std::swap (this->value , t.value );
371 std::swap (this->id , t.id );
372 std::swap (this->variant, t.variant);
373 std::swap (this->err , t.err );
376 Time &operator= (Time t) NOEXCEPT;
378 Time &operator= (struct timespec ts) NOEXCEPT;
381 set (const struct timespec &ts) NOEXCEPT
388 set (const time_t sec,
390 const enum type::id id = type::mono,
391 const enum type::variant var = type::dflt) NOEXCEPT
393 this->value.tv_sec = sec;
394 this->value.tv_nsec = nsec;
401 bool set (void) NOEXCEPT;
403 void unset (void) NOEXCEPT;
405 /* arithmetic ********************************************************/
408 Time &add (const time_t sec, const long nsec) NOEXCEPT;
410 Time &subtract (const time_t sec, const long nsec) NOEXCEPT;
412 inline Time &add (const Time &t2) NOEXCEPT
413 { return this->add (t2.value.tv_sec, t2.value.tv_nsec); }
415 inline Time &add (const time_t t2) NOEXCEPT
416 { return this->add (t2, 0L); };
418 inline Time &subtract (const Time &t2) NOEXCEPT
419 { return this->subtract (t2.value.tv_sec, t2.value.tv_nsec); }
421 inline Time &subtract (const time_t t2) NOEXCEPT
422 { return this->subtract (t2, 0L); };
424 Time &scale (const time_t factor) NOEXCEPT;
426 friend int compare (const Time &t1, const Time &t2) NOEXCEPT;
429 difference (const Time &t) NOEXCEPT
430 { return (*this < t) ? t - *this : *this - t; }
432 /* overloads *********************************************************/
436 operator+ (const Time &t2) const NOEXCEPT
437 { return Time (*this).add (t2); }
440 operator+ (const time_t t2) const NOEXCEPT
441 { return Time (*this).add (t2); }
444 operator+= (const Time &t2) NOEXCEPT
445 { return this->add (t2); }
448 operator+= (const time_t t2) NOEXCEPT
449 { return this->add (t2); }
452 operator- (const Time &t2) const NOEXCEPT
453 { return Time (*this).subtract (t2); }
456 operator- (const time_t t2) const NOEXCEPT
457 { return Time (*this).subtract (t2); }
460 operator-= (const Time &t2) NOEXCEPT
461 { return this->subtract (t2); }
464 operator-= (const time_t t2) NOEXCEPT
465 { return this->subtract (t2); }
468 operator* (const time_t factor) const NOEXCEPT
469 { return Time (*this).scale (factor); }
472 operator*= (const time_t factor) NOEXCEPT
473 { return this->scale (factor); }
475 friend CONSTEXPR bool
476 operator== (const Time &t1, const Time &t2) NOEXCEPT;
478 friend CONSTEXPR bool
479 operator< (const Time &t1, const Time &t2) NOEXCEPT;
481 friend CONSTEXPR bool
482 operator> (const Time &t1, const Time &t2) NOEXCEPT;
484 friend std::ostream &
485 operator<< (std::ostream &os, const Time &t);
487 }; /* [class Time] */
490 operator+ (const time_t t1, const Time &t2) NOEXCEPT
491 { return Time (t1) + t2; }
494 operator- (const time_t t1, const Time &t2) NOEXCEPT
495 { return Time (t1) - t2; }
497 int compare (const Time &t1, const Time &t2) NOEXCEPT;
500 * comparison for equality also considers the clock type;
502 inline CONSTEXPR bool
503 operator== (const Time &t1, const Time &t2) NOEXCEPT
505 return t1.id == t2.id && t1.variant == t2.variant
506 && t1.value.tv_sec == t2.value.tv_sec
507 && t1.value.tv_nsec == t2.value.tv_nsec
511 /* these ignore the *id* and *variant* fields */
512 inline CONSTEXPR bool
513 operator< (const Time &t1, const Time &t2) NOEXCEPT
515 return t1.value.tv_sec < t2.value.tv_sec
516 || ( t1.value.tv_sec == t2.value.tv_sec
517 && t1.value.tv_nsec < t2.value.tv_nsec)
521 /* these ignore the *id* and *variant* fields */
522 inline CONSTEXPR bool
523 operator> (const Time &t1, const Time &t2) NOEXCEPT
525 return t1.value.tv_sec > t2.value.tv_sec
526 || ( t1.value.tv_sec == t2.value.tv_sec
527 && t1.value.tv_nsec > t2.value.tv_nsec)
531 inline std::ostream &
532 operator<< (std::ostream &os, const Time &t)
534 os << I2n::to_string (t.value.tv_sec) << "ms, "
535 << I2n::to_string (t.value.tv_nsec) << "ns"
541 boost::optional<Time>
542 now (const enum type::id id = type::mono,
543 const enum type::variant var = type::dflt) NOEXCEPT;
546 zero (const enum type::id id = type::mono,
547 const enum type::variant var = type::dflt) NOEXCEPT;
549 } /* [namespace clock] */
551 } /* [namespace I2n] */