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
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 std::string format_iso8601(const struct tm &tm, const bool date=true,
58 const bool time=true, const bool tz=true);
59 std::string format_iso8601(time_t t, const bool utc=true,
60 const bool date=true, const bool time=true,
62 inline std::string format_iso8601(const struct timespec ts, const bool utc=true,
63 const bool date=true, const bool time=true,
65 { return format_iso8601 (ts.tv_sec, utc, date, time, tz); }
67 void seconds_to_hour_minute(int seconds, int *hour, int *minute);
68 void split_daysec(int daysec, int *outhours=NULL, int *outminutes=NULL, int *outseconds=NULL);
69 std::string output_hour_minute(int hour, int minute, bool h_for_00=true, int seconds=0);
71 inline std::string output_hour_minute_from_seconds(int seconds)
74 split_daysec(seconds,&hour,&minute);
75 return output_hour_minute(hour,minute);
78 std::string get_month_name(unsigned char month);
81 * @brief structure representing a single (half-open) interval.
94 Interval( unsigned int start, unsigned int end, int weak_mark= 0 )
95 : m_lower_bound(start)
97 , m_weak_mark(weak_mark)
105 bool is_valid() const
107 return m_lower_bound <= m_upper_bound;
108 } // eo is_valid() const
112 return m_lower_bound == m_upper_bound;
113 } // eo empty() const
116 unsigned int lower_bound() const { return m_lower_bound; }
117 unsigned int upper_bound() const { return m_upper_bound; }
119 int weak_mark() const { return m_weak_mark; }
121 bool changed() const { return m_changed; }
124 bool operator== (const Interval& other) const
126 return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound;
127 } // eo operator==(const Interval&)
130 bool operator!=(const Interval& other) const
132 return not (*this == other);
133 } // eo operator!=(const Interval&)
137 * @brief less operator. compares only the start times!
138 * @param other the other interval to compare with.
139 * @return @a true if the current start is less than the other start.
141 bool operator<(const Interval& other) const
143 return m_lower_bound < other.m_lower_bound;
144 } // eo operator<(const Interval&)
147 bool intersects(const Interval& other) const;
148 bool contains(const Interval& other) const;
153 friend class Intervals;
155 unsigned int m_lower_bound;
156 unsigned int m_upper_bound;
166 * @brief structure representing a combination of single disjoint (half open) intervals.
168 * Basic idea is that this structure provides an interface for adding and
169 * subtracting single intervals and keeps the internal list of intervals as
170 * a list of disjoint intervals.
172 * @note the list is sorted by the start; lower comes first.
174 * @note the class provides some methods similar to STL container classes;
175 * i.e. it can be used with (at least some) STL algorithms.
178 * we use a std::list for the intervals; this means we don't invalidate all
179 * iterators when we insert or delete within loops...
180 * And we use that fact!!
185 typedef std::list< Interval > IntervalList;
186 typedef IntervalList::value_type value_type;
187 typedef IntervalList::const_iterator const_iterator;
188 typedef IntervalList::const_iterator iterator; // we allow only const...
189 typedef IntervalList::size_type size_type;
194 void add(const Interval& new_frame);
195 void sub(const Interval& new_frame);
199 const_iterator begin() const { return m_intervals.begin(); }
200 const_iterator end() const { return m_intervals.end(); }
202 bool empty() const { return m_intervals.empty(); }
203 const Interval& front() const { return m_intervals.front(); }
204 const Interval& back() const { return m_intervals.back(); }
206 size_type size() const { return m_intervals.size(); }
208 bool intersects(const Interval& other) const;
209 bool intersects(const Intervals& other) const;
211 bool contains(const Interval& other) const;
212 bool contains(const Intervals& other) const;
214 bool contains_exact(const Interval& other) const;
216 bool operator==(const Intervals& other) const;
217 bool operator!=(const Intervals& other) const { return not (*this == other) ; }
219 Intervals& operator+=(const Interval& other);
220 Intervals& operator-=(const Interval& other);
222 Intervals& operator+=(const Intervals& other);
223 Intervals& operator-=(const Intervals& other);
227 std::list< Interval > m_intervals;
237 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds);
238 long long monotonic_clock_gettime_nano();
240 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds);
248 /* helper for ctor initializer list; we still lack aggregate initializers */
250 timespec_of_parts (const time_t sec, const long nsec)
252 struct timespec ret = { sec, nsec};
261 * represent the clock id options from clock_gettime(2) as
262 * a pair of enums. by default, CLOCK_MONOTONIC_COARSE is used
263 * everywhere since that’s what we want in most cases.
266 mono, /* CLOCK_MONOTONIC_COARSE */
267 real, /* CLOCK_REALIME_COARSE */
268 boot, /* CLOCK_BOOTTIME */
269 cpu, /* CLOCK_CPUTIME_* */
273 * for clocks that support it: non-coarse or raw variants; if a variant
274 * does not apply to a given clock, it is ignored
278 exact, /* mono, real: not (*_COARSE) */
279 raw, /* mono: _RAW */
280 process, /* cpu: *_PROCESS_* */
281 thread, /* cpu: *_THREAD_* */
284 } /* [namespace type] */
290 struct timespec value;
294 enum type::variant variant;
299 * Handle decimal part (nanosecond) overflow; this is performed
300 * after arithmetic operations and whenever we there is the
301 * possibility of unsanitized input for example in constructors
302 * from other types and suchlike.
304 * POSIX defines the ns part as *long*. Technically, that means
305 * that on machines where *sizeof long* equals *sizeof int*, it can
306 * represent only up to arund 2.1 seconds. In this range, the loop
307 * version is most likely faster than division. However, since in
308 * practice *long* is 8 bytes just about anywhere, we have to
309 * handle greater dividends first.
315 if ( this->value.tv_nsec < -3L * TIME_CONST_FACTOR_NANO
316 || this->value.tv_nsec > 3L * TIME_CONST_FACTOR_NANO)
318 const long sec = this->value.tv_nsec / TIME_CONST_FACTOR_NANO;
319 this->value.tv_nsec -= sec * TIME_CONST_FACTOR_NANO;
320 this->value.tv_sec += sec;
322 # endif /* [LONG_BIT > 32] */
323 while (this->value.tv_nsec >= TIME_CONST_FACTOR_NANO) {
324 this->value.tv_sec += 1;
325 this->value.tv_nsec -= TIME_CONST_FACTOR_NANO;
328 while (this->value.tv_nsec < 0) {
329 this->value.tv_sec -= 1;
330 this->value.tv_nsec += TIME_CONST_FACTOR_NANO;
334 /* ctors *************************************************************/
337 Time (const enum type::id id = type::mono,
338 const enum type::variant var = type::dflt) NOEXCEPT;
340 inline Time (const Time &t) NOEXCEPT
343 , variant (t.variant)
347 inline Time (const time_t sec,
349 const enum type::id id = type::mono,
350 const enum type::variant var = type::dflt,
351 const int err = 0) NOEXCEPT
352 : value (timespec_of_parts (sec, nsec))
356 { this->carry_nsec (); }
358 /* value read access *************************************************/
361 inline CONSTEXPR const struct timespec &get_time (void) const NOEXCEPT
362 { return this->value; }
364 inline CONSTEXPR const time_t &get_sec (void) const NOEXCEPT
365 { return this->value.tv_sec; }
367 inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT
368 { return this->value.tv_nsec; }
370 int64_t as_nanosec (void) const NOEXCEPT;
372 long as_nanosec_L (void) const NOEXCEPT;
374 /* value write access ************************************************/
378 swap (Time &t) NOEXCEPT
380 std::swap (this->value , t.value );
381 std::swap (this->id , t.id );
382 std::swap (this->variant, t.variant);
383 std::swap (this->err , t.err );
386 Time &operator= (Time t) NOEXCEPT;
388 Time &operator= (struct timespec ts) NOEXCEPT;
391 set (const struct timespec &ts) NOEXCEPT
398 set (const time_t sec,
400 const enum type::id id = type::mono,
401 const enum type::variant var = type::dflt) NOEXCEPT
403 this->value.tv_sec = sec;
404 this->value.tv_nsec = nsec;
411 bool set (void) NOEXCEPT;
413 void unset (void) NOEXCEPT;
415 /* arithmetic ********************************************************/
418 Time &add (const time_t sec, const long nsec) NOEXCEPT;
420 Time &subtract (const time_t sec, const long nsec) NOEXCEPT;
422 inline Time &add (const Time &t2) NOEXCEPT
423 { return this->add (t2.value.tv_sec, t2.value.tv_nsec); }
425 inline Time &add (const time_t t2) NOEXCEPT
426 { return this->add (t2, 0L); };
428 inline Time &subtract (const Time &t2) NOEXCEPT
429 { return this->subtract (t2.value.tv_sec, t2.value.tv_nsec); }
431 inline Time &subtract (const time_t t2) NOEXCEPT
432 { return this->subtract (t2, 0L); };
434 Time &scale (const time_t factor) NOEXCEPT;
436 friend int compare (const Time &t1, const Time &t2) NOEXCEPT;
439 difference (const Time &t) NOEXCEPT
440 { return (*this < t) ? t - *this : *this - t; }
442 /* overloads *********************************************************/
446 operator+ (const Time &t2) const NOEXCEPT
447 { return Time (*this).add (t2); }
450 operator+ (const time_t t2) const NOEXCEPT
451 { return Time (*this).add (t2); }
454 operator+= (const Time &t2) NOEXCEPT
455 { return this->add (t2); }
458 operator+= (const time_t t2) NOEXCEPT
459 { return this->add (t2); }
462 operator- (const Time &t2) const NOEXCEPT
463 { return Time (*this).subtract (t2); }
466 operator- (const time_t t2) const NOEXCEPT
467 { return Time (*this).subtract (t2); }
470 operator-= (const Time &t2) NOEXCEPT
471 { return this->subtract (t2); }
474 operator-= (const time_t t2) NOEXCEPT
475 { return this->subtract (t2); }
478 operator* (const time_t factor) const NOEXCEPT
479 { return Time (*this).scale (factor); }
482 operator*= (const time_t factor) NOEXCEPT
483 { return this->scale (factor); }
485 friend CONSTEXPR bool
486 operator== (const Time &t1, const Time &t2) NOEXCEPT;
488 friend CONSTEXPR bool
489 operator< (const Time &t1, const Time &t2) NOEXCEPT;
491 friend CONSTEXPR bool
492 operator> (const Time &t1, const Time &t2) NOEXCEPT;
494 friend std::ostream &
495 operator<< (std::ostream &os, const Time &t);
497 }; /* [class Time] */
500 operator+ (const time_t t1, const Time &t2) NOEXCEPT
501 { return Time (t1) + t2; }
504 operator- (const time_t t1, const Time &t2) NOEXCEPT
505 { return Time (t1) - t2; }
507 int compare (const Time &t1, const Time &t2) NOEXCEPT;
510 * comparison for equality also considers the clock type;
512 inline CONSTEXPR bool
513 operator== (const Time &t1, const Time &t2) NOEXCEPT
515 return t1.id == t2.id && t1.variant == t2.variant
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 /* these ignore the *id* and *variant* fields */
532 inline CONSTEXPR bool
533 operator> (const Time &t1, const Time &t2) NOEXCEPT
535 return t1.value.tv_sec > t2.value.tv_sec
536 || ( t1.value.tv_sec == t2.value.tv_sec
537 && t1.value.tv_nsec > t2.value.tv_nsec)
541 inline std::ostream &
542 operator<< (std::ostream &os, const Time &t)
544 os << I2n::to_string (t.value.tv_sec) << "ms, "
545 << I2n::to_string (t.value.tv_nsec) << "ns"
551 boost::optional<Time>
552 now (const enum type::id id = type::mono,
553 const enum type::variant var = type::dflt) NOEXCEPT;
556 zero (const enum type::id id = type::mono,
557 const enum type::variant var = type::dflt) NOEXCEPT;
559 } /* [namespace clock] */
561 } /* [namespace I2n] */