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 boost::optional<struct tm> scan_iso8601 (const char *s,
68 const bool date=true, const bool time=true,
69 const bool tz=true) NOEXCEPT;
70 inline boost::optional<struct tm> scan_iso8601 (const std::string &s,
73 const bool tz=true) NOEXCEPT
74 { return scan_iso8601 (s.c_str (), date, time, tz); }
77 void seconds_to_hour_minute(int seconds, int *hour, int *minute);
78 void split_daysec(int daysec, int *outhours=NULL, int *outminutes=NULL, int *outseconds=NULL);
79 std::string output_hour_minute(int hour, int minute, bool h_for_00=true, int seconds=0);
81 inline std::string output_hour_minute_from_seconds(int seconds)
84 split_daysec(seconds,&hour,&minute);
85 return output_hour_minute(hour,minute);
88 std::string get_month_name(unsigned char month);
91 * @brief structure representing a single (half-open) interval.
104 Interval( unsigned int start, unsigned int end, int weak_mark= 0 )
105 : m_lower_bound(start)
107 , m_weak_mark(weak_mark)
115 bool is_valid() const
117 return m_lower_bound <= m_upper_bound;
118 } // eo is_valid() const
122 return m_lower_bound == m_upper_bound;
123 } // eo empty() const
126 unsigned int lower_bound() const { return m_lower_bound; }
127 unsigned int upper_bound() const { return m_upper_bound; }
129 int weak_mark() const { return m_weak_mark; }
131 bool changed() const { return m_changed; }
134 bool operator== (const Interval& other) const
136 return m_lower_bound == other.m_lower_bound and m_upper_bound == other.m_upper_bound;
137 } // eo operator==(const Interval&)
140 bool operator!=(const Interval& other) const
142 return not (*this == other);
143 } // eo operator!=(const Interval&)
147 * @brief less operator. compares only the start times!
148 * @param other the other interval to compare with.
149 * @return @a true if the current start is less than the other start.
151 bool operator<(const Interval& other) const
153 return m_lower_bound < other.m_lower_bound;
154 } // eo operator<(const Interval&)
157 bool intersects(const Interval& other) const;
158 bool contains(const Interval& other) const;
163 friend class Intervals;
165 unsigned int m_lower_bound;
166 unsigned int m_upper_bound;
176 * @brief structure representing a combination of single disjoint (half open) intervals.
178 * Basic idea is that this structure provides an interface for adding and
179 * subtracting single intervals and keeps the internal list of intervals as
180 * a list of disjoint intervals.
182 * @note the list is sorted by the start; lower comes first.
184 * @note the class provides some methods similar to STL container classes;
185 * i.e. it can be used with (at least some) STL algorithms.
188 * we use a std::list for the intervals; this means we don't invalidate all
189 * iterators when we insert or delete within loops...
190 * And we use that fact!!
195 typedef std::list< Interval > IntervalList;
196 typedef IntervalList::value_type value_type;
197 typedef IntervalList::const_iterator const_iterator;
198 typedef IntervalList::const_iterator iterator; // we allow only const...
199 typedef IntervalList::size_type size_type;
204 void add(const Interval& new_frame);
205 void sub(const Interval& new_frame);
209 const_iterator begin() const { return m_intervals.begin(); }
210 const_iterator end() const { return m_intervals.end(); }
212 bool empty() const { return m_intervals.empty(); }
213 const Interval& front() const { return m_intervals.front(); }
214 const Interval& back() const { return m_intervals.back(); }
216 size_type size() const { return m_intervals.size(); }
218 bool intersects(const Interval& other) const;
219 bool intersects(const Intervals& other) const;
221 bool contains(const Interval& other) const;
222 bool contains(const Intervals& other) const;
224 bool contains_exact(const Interval& other) const;
226 bool operator==(const Intervals& other) const;
227 bool operator!=(const Intervals& other) const { return not (*this == other) ; }
229 Intervals& operator+=(const Interval& other);
230 Intervals& operator-=(const Interval& other);
232 Intervals& operator+=(const Intervals& other);
233 Intervals& operator-=(const Intervals& other);
237 std::list< Interval > m_intervals;
247 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds);
248 long long monotonic_clock_gettime_nano();
250 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds);
258 /* helper for ctor initializer list; we still lack aggregate initializers */
260 timespec_of_parts (const time_t sec, const long nsec)
262 struct timespec ret = { sec, nsec};
271 * represent the clock id options from clock_gettime(2) as
272 * a pair of enums. by default, CLOCK_MONOTONIC_COARSE is used
273 * everywhere since that’s what we want in most cases.
276 mono, /* CLOCK_MONOTONIC_COARSE */
277 real, /* CLOCK_REALIME_COARSE */
278 boot, /* CLOCK_BOOTTIME */
279 cpu, /* CLOCK_CPUTIME_* */
283 * for clocks that support it: non-coarse or raw variants; if a variant
284 * does not apply to a given clock, it is ignored
288 exact, /* mono, real: not (*_COARSE) */
289 raw, /* mono: _RAW */
290 process, /* cpu: *_PROCESS_* */
291 thread, /* cpu: *_THREAD_* */
294 } /* [namespace type] */
300 struct timespec value;
304 enum type::variant variant;
309 * Handle decimal part (nanosecond) overflow; this is performed
310 * after arithmetic operations and whenever we there is the
311 * possibility of unsanitized input for example in constructors
312 * from other types and suchlike.
314 * POSIX defines the ns part as *long*. Technically, that means
315 * that on machines where *sizeof long* equals *sizeof int*, it can
316 * represent only up to arund 2.1 seconds. In this range, the loop
317 * version is most likely faster than division. However, since in
318 * practice *long* is 8 bytes just about anywhere, we have to
319 * handle greater dividends first.
325 if ( this->value.tv_nsec < -3L * TIME_CONST_FACTOR_NANO
326 || this->value.tv_nsec > 3L * TIME_CONST_FACTOR_NANO)
328 const long sec = this->value.tv_nsec / TIME_CONST_FACTOR_NANO;
329 this->value.tv_nsec -= sec * TIME_CONST_FACTOR_NANO;
330 this->value.tv_sec += sec;
332 # endif /* [LONG_BIT > 32] */
333 while (this->value.tv_nsec >= TIME_CONST_FACTOR_NANO) {
334 this->value.tv_sec += 1;
335 this->value.tv_nsec -= TIME_CONST_FACTOR_NANO;
338 while (this->value.tv_nsec < 0) {
339 this->value.tv_sec -= 1;
340 this->value.tv_nsec += TIME_CONST_FACTOR_NANO;
344 /* ctors *************************************************************/
347 Time (const enum type::id id = type::mono,
348 const enum type::variant var = type::dflt) NOEXCEPT;
350 inline Time (const Time &t) NOEXCEPT
353 , variant (t.variant)
357 inline Time (const time_t sec,
359 const enum type::id id = type::mono,
360 const enum type::variant var = type::dflt,
361 const int err = 0) NOEXCEPT
362 : value (timespec_of_parts (sec, nsec))
366 { this->carry_nsec (); }
368 Time (const struct tm &tm,
369 const enum type::id id = type::mono,
370 const enum type::variant var = type::dflt) NOEXCEPT;
372 /* value read access *************************************************/
375 inline CONSTEXPR const struct timespec &get_time (void) const NOEXCEPT
376 { return this->value; }
378 inline CONSTEXPR const time_t &get_sec (void) const NOEXCEPT
379 { return this->value.tv_sec; }
381 inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT
382 { return this->value.tv_nsec; }
384 int64_t as_nanosec (void) const NOEXCEPT;
386 long as_nanosec_L (void) const NOEXCEPT;
388 /* value write access ************************************************/
392 swap (Time &t) NOEXCEPT
394 std::swap (this->value , t.value );
395 std::swap (this->id , t.id );
396 std::swap (this->variant, t.variant);
397 std::swap (this->err , t.err );
400 Time &operator= (Time t) NOEXCEPT;
402 Time &operator= (struct timespec ts) NOEXCEPT;
405 set (const struct timespec &ts) NOEXCEPT
412 set (const time_t sec,
414 const enum type::id id = type::mono,
415 const enum type::variant var = type::dflt) NOEXCEPT
417 this->value.tv_sec = sec;
418 this->value.tv_nsec = nsec;
425 bool set (void) NOEXCEPT;
427 void unset (void) NOEXCEPT;
429 /* arithmetic ********************************************************/
432 Time &add (const time_t sec, const long nsec) NOEXCEPT;
434 Time &subtract (const time_t sec, const long nsec) NOEXCEPT;
436 inline Time &add (const Time &t2) NOEXCEPT
437 { return this->add (t2.value.tv_sec, t2.value.tv_nsec); }
439 inline Time &add (const time_t t2) NOEXCEPT
440 { return this->add (t2, 0L); };
442 inline Time &subtract (const Time &t2) NOEXCEPT
443 { return this->subtract (t2.value.tv_sec, t2.value.tv_nsec); }
445 inline Time &subtract (const time_t t2) NOEXCEPT
446 { return this->subtract (t2, 0L); };
448 Time &scale (const time_t factor) NOEXCEPT;
450 friend int compare (const Time &t1, const Time &t2) NOEXCEPT;
453 difference (const Time &t) NOEXCEPT
454 { return (*this < t) ? t - *this : *this - t; }
456 /* overloads *********************************************************/
460 operator+ (const Time &t2) const NOEXCEPT
461 { return Time (*this).add (t2); }
464 operator+ (const time_t t2) const NOEXCEPT
465 { return Time (*this).add (t2); }
468 operator+= (const Time &t2) NOEXCEPT
469 { return this->add (t2); }
472 operator+= (const time_t t2) NOEXCEPT
473 { return this->add (t2); }
476 operator- (const Time &t2) const NOEXCEPT
477 { return Time (*this).subtract (t2); }
480 operator- (const time_t t2) const NOEXCEPT
481 { return Time (*this).subtract (t2); }
484 operator-= (const Time &t2) NOEXCEPT
485 { return this->subtract (t2); }
488 operator-= (const time_t t2) NOEXCEPT
489 { return this->subtract (t2); }
492 operator* (const time_t factor) const NOEXCEPT
493 { return Time (*this).scale (factor); }
496 operator*= (const time_t factor) NOEXCEPT
497 { return this->scale (factor); }
499 friend CONSTEXPR bool
500 operator== (const Time &t1, const Time &t2) NOEXCEPT;
502 friend CONSTEXPR bool
503 operator< (const Time &t1, const Time &t2) NOEXCEPT;
505 friend CONSTEXPR bool
506 operator> (const Time &t1, const Time &t2) NOEXCEPT;
508 friend std::ostream &
509 operator<< (std::ostream &os, const Time &t);
511 /* formatting ********************************************************/
514 boost::optional<std::string>
515 format_iso8601 (const bool utc = true,
516 const bool date = true,
517 const bool time = true,
518 const bool tz = true) const;
520 boost::optional<std::string> make_nice_time (void) const;
521 boost::optional<std::string> format_full_time (void) const;
522 boost::optional<std::string> format_date (void) const;
524 }; /* [class Time] */
527 operator+ (const time_t t1, const Time &t2) NOEXCEPT
528 { return Time (t1) + t2; }
531 operator- (const time_t t1, const Time &t2) NOEXCEPT
532 { return Time (t1) - t2; }
534 int compare (const Time &t1, const Time &t2) NOEXCEPT;
537 * comparison for equality also considers the clock type;
539 inline CONSTEXPR bool
540 operator== (const Time &t1, const Time &t2) NOEXCEPT
542 return t1.id == t2.id && t1.variant == t2.variant
543 && t1.value.tv_sec == t2.value.tv_sec
544 && t1.value.tv_nsec == t2.value.tv_nsec
548 /* these ignore the *id* and *variant* fields */
549 inline CONSTEXPR bool
550 operator< (const Time &t1, const Time &t2) NOEXCEPT
552 return t1.value.tv_sec < t2.value.tv_sec
553 || ( t1.value.tv_sec == t2.value.tv_sec
554 && t1.value.tv_nsec < t2.value.tv_nsec)
558 /* these ignore the *id* and *variant* fields */
559 inline CONSTEXPR bool
560 operator> (const Time &t1, const Time &t2) NOEXCEPT
562 return t1.value.tv_sec > t2.value.tv_sec
563 || ( t1.value.tv_sec == t2.value.tv_sec
564 && t1.value.tv_nsec > t2.value.tv_nsec)
568 inline std::ostream &
569 operator<< (std::ostream &os, const Time &t)
571 os << I2n::to_string (t.value.tv_sec) << "ms, "
572 << I2n::to_string (t.value.tv_nsec) << "ns"
578 boost::optional<Time>
579 now (const enum type::id id = type::mono,
580 const enum type::variant var = type::dflt) NOEXCEPT;
583 zero (const enum type::id id = type::mono,
584 const enum type::variant var = type::dflt) NOEXCEPT;
586 boost::optional<Time>
587 time_of_iso8601 (const std::string &s,
588 const bool date = true,
589 const bool time = true,
590 const bool tz = true,
591 const enum type::id id = type::real,
592 const enum type::variant var = type::dflt) NOEXCEPT;
594 } /* [namespace clock] */
596 } /* [namespace I2n] */