/** @file
* @brief time related functions.
*
- * @copyright Copyright © 2001-2008 by Intra2net AG
+ * @copyright Copyright © 2001-2018 by Intra2net AG
*/
#ifndef __TIMEFUNC_HXX
#include <errno.h>
#include <list>
#include <string>
+#include <cstdlib>
#include <boost/optional.hpp>
std::string make_nice_time(int seconds);
std::string format_full_time(time_t seconds);
std::string format_date(time_t seconds);
+std::string format_iso8601(const struct tm &tm, const bool date=true,
+ const bool time=true, const bool tz=true);
+std::string format_iso8601(time_t t, const bool utc=true,
+ const bool date=true, const bool time=true,
+ const bool tz=true);
+
+inline std::string format_iso8601(const struct timespec &ts, const bool utc=true,
+ const bool date=true, const bool time=true,
+ const bool tz=true)
+{ return format_iso8601 (ts.tv_sec, utc, date, time, tz); }
+
+inline std::string format_sec_msec (const struct timespec &ts)
+{
+ return I2n::to_string (ts.tv_sec) + "s "
+ + I2n::to_string (ts.tv_nsec / 1000000) + "ms"
+ ;
+}
+
+boost::optional<std::string> format_min_sec_msec (const struct timespec &ts);
+
+boost::optional<struct tm> scan_iso8601 (const char *s,
+ const bool date=true, const bool time=true,
+ const bool tz=true) NOEXCEPT;
+inline boost::optional<struct tm> scan_iso8601 (const std::string &s,
+ const bool date=true,
+ const bool time=true,
+ const bool tz=true) NOEXCEPT
+{ return scan_iso8601 (s.c_str (), date, time, tz); }
+
+
void seconds_to_hour_minute(int seconds, int *hour, int *minute);
void split_daysec(int daysec, int *outhours=NULL, int *outminutes=NULL, int *outseconds=NULL);
std::string output_hour_minute(int hour, int minute, bool h_for_00=true, int seconds=0);
namespace clock {
+ class conversion_error : public std::exception
+ {
+ public:
+ const int err;
+ const std::string context;
+
+ conversion_error (const int err, const std::string &context)
+ : err (err)
+ , context (context)
+ { }
+
+ virtual ~conversion_error (void) throw() { };
+
+ operator std::string (void)
+ {
+ return std::string ("errno=") + I2n::to_string (this->err)
+ + " [" + this->context + "]";
+ }
+ };
+
namespace {
/* helper for ctor initializer list; we still lack aggregate initializers */
*
* POSIX defines the ns part as *long*. Technically, that means
* that on machines where *sizeof long* equals *sizeof int*, it can
- * represent only up to arund 2.1 seconds. In this range, the loop
+ * represent only up to around 2.1 seconds. In this range, the loop
* version is most likely faster than division. However, since in
* practice *long* is 8 bytes just about anywhere, we have to
* handle greater dividends first.
, err (t.err)
{ }
- inline Time (const time_t sec,
- const long nsec = 0,
- const enum type::id id = type::mono,
- const enum type::variant var = type::dflt,
- const int err = 0) NOEXCEPT
+ inline
+ Time (const time_t sec,
+ const long nsec = 0,
+ const enum type::id id = type::mono,
+ const enum type::variant var = type::dflt,
+ const int err = 0) NOEXCEPT
: value (timespec_of_parts (sec, nsec))
, id (id)
, variant (var)
, err (err)
{ this->carry_nsec (); }
+ explicit
+ Time (const struct tm &tm,
+ const enum type::id id = type::mono,
+ const enum type::variant var = type::dflt);
+
/* value read access *************************************************/
public:
inline CONSTEXPR const long &get_nsec (void) const NOEXCEPT
{ return this->value.tv_nsec; }
+ inline CONSTEXPR const long get_msec (void) const NOEXCEPT
+ { return this->get_nsec () / 1000000; }
+
int64_t as_nanosec (void) const NOEXCEPT;
long as_nanosec_L (void) const NOEXCEPT;
inline Time &subtract (const time_t t2) NOEXCEPT
{ return this->subtract (t2, 0L); };
- Time &scale (const time_t factor) NOEXCEPT;
+ Time &scale (const int64_t factor) NOEXCEPT;
+
+ Time ÷ (const int64_t divisor) NOEXCEPT;
friend int compare (const Time &t1, const Time &t2) NOEXCEPT;
{ return this->subtract (t2); }
inline Time
- operator* (const time_t factor) const NOEXCEPT
+ operator* (const int64_t factor) const NOEXCEPT
{ return Time (*this).scale (factor); }
inline Time &
- operator*= (const time_t factor) NOEXCEPT
+ operator*= (const int64_t factor) NOEXCEPT
{ return this->scale (factor); }
+ inline Time
+ operator/ (const int64_t divisor) const NOEXCEPT
+ { return Time (*this).divide (divisor); }
+
+ inline Time &
+ operator/= (const int64_t divisor) NOEXCEPT
+ { return this->divide (divisor); }
+
friend CONSTEXPR bool
operator== (const Time &t1, const Time &t2) NOEXCEPT;
friend std::ostream &
operator<< (std::ostream &os, const Time &t);
+ /* formatting ********************************************************/
+ public:
+
+ boost::optional<std::string>
+ format_iso8601 (const bool utc = true,
+ const bool date = true,
+ const bool time = true,
+ const bool tz = true) const;
+
+ std::string make_nice_time (void) const;
+ std::string format_full_time (void) const;
+ std::string format_date (void) const;
+
+ inline std::string
+ format_sec_msec (void) const
+ { return ::format_sec_msec (this->value); }
+
+ inline boost::optional<std::string>
+ format_min_sec_msec (void) const
+ { return ::format_min_sec_msec (this->value); }
+
}; /* [class Time] */
inline Time
operator- (const time_t t1, const Time &t2) NOEXCEPT
{ return Time (t1) - t2; }
+ inline Time
+ operator* (const time_t t1, const Time &t2) NOEXCEPT
+ { return t2 * t1; }
+
int compare (const Time &t1, const Time &t2) NOEXCEPT;
/*
inline std::ostream &
operator<< (std::ostream &os, const Time &t)
{
- os << I2n::to_string (t.value.tv_sec) << "ms, "
+ os << I2n::to_string (t.value.tv_sec) << "s, "
<< I2n::to_string (t.value.tv_nsec) << "ns"
;
zero (const enum type::id id = type::mono,
const enum type::variant var = type::dflt) NOEXCEPT;
+ boost::optional<Time>
+ time_of_iso8601 (const std::string &s,
+ const bool date = true,
+ const bool time = true,
+ const bool tz = true,
+ const enum type::id id = type::real,
+ const enum type::variant var = type::dflt) NOEXCEPT;
+
+ template <typename ContT>
+ Time
+ mean (const ContT &data)
+ {
+ Time sum (0, 0);
+
+ if (data.size () == 0) {
+ return sum;
+ }
+
+ for (typename ContT::const_iterator it = data.begin ();
+ it != data.end (); ++it)
+ {
+ sum += *it;
+ };
+
+ return sum.divide (static_cast<int64_t> (data.size ()));
+ };
+
+ template <typename ContT>
+ Time
+ median (const ContT &data)
+ {
+ if (data.size () == 0) {
+ return zero ();
+ }
+ if (data.size () == 1) {
+ return *data.begin ();
+ }
+
+ std::vector<typename ContT::value_type> sorted;
+ std::copy (data.begin (), data.end (), std::back_inserter (sorted));
+ std::sort (sorted.begin (), sorted.end ());
+
+ return sorted [data.size () / 2];
+ };
+
} /* [namespace clock] */
} /* [namespace I2n] */