-/***************************************************************************
- timecvt.cpp - description
- -------------------
- begin : Fri May 11 2001
- copyright : (C) 2001 by STYLETEC
- email : info@styletec.de
- ***************************************************************************/
+/*
+The software in this package is distributed under the GNU General
+Public License version 2 (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.GPL.
+
+As a special exception, if other files instantiate templates or use macros
+or inline functions from this file, or you compile this file and link it
+with other works to produce a work based on this file, this file
+does not by itself cause the resulting work to be covered
+by the GNU General Public License.
+
+However the source code for this file must still be made available
+in accordance with section (3) of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based
+on this file might be covered by the GNU General Public License.
+*/
+/** @file
+ * @brief time related functions.
+ *
+ * @copyright Copyright © 2001-2008 by Intra2net AG
+ *
+ */
#include <string>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <stdexcept>
+#include <iterator>
+#include <algorithm>
#include <time.h>
+#include <unistd.h>
+#include <string.h>
#include <sys/timeb.h>
#include <timefunc.hxx>
#include <i18n.h>
+
+// define missing POSIX.1b constants...
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+#ifndef CLOCK_MONOTONIC
+#define CLOCK_MONOTONIC 1
+#endif
+
+
+
using namespace std;
double prec_time(void)
}
// converts ISO-DATE: 2003-06-13
-int date_to_seconds(const std::string &date)
+time_t date_to_seconds(const std::string &date)
{
- int rtn = -1, year = -1, month = -1, day = -1;
+ time_t rtn = 0;
+ int year = -1, month = -1, day = -1;
string::size_type pos = date.find("-");
if (pos == string::npos)
if (year < 0 || month == -1 || day == -1)
return rtn;
-
+
struct tm tm_struct;
- bzero (&tm_struct, sizeof(struct tm));
+ memset(&tm_struct, 0, sizeof(struct tm));
tm_struct.tm_year = year;
tm_struct.tm_mon = month;
tm_struct.tm_mday = day;
int days=seconds/86400;
seconds%=86400;
- int hours=seconds/3600;
- seconds%=3600;
-
- int minutes=seconds/60;
- seconds%=60;
-
- if (days==1)
- out << i18n("1 day") << ", ";
- else if (days>1)
- out << days << ' ' << i18n("days") << ", ";
+ int hours,minutes;
+ split_daysec(seconds,&hours,&minutes,&seconds);
+
+ if (days>0)
+ out << days << " " << i18n_plural("day", "days", days) << ", ";
out << setfill('0');
out << setw(2) << hours << ':' << setw(2) << minutes << ':' << setw(2) << seconds;
return out.str();
}
-string format_full_time(int seconds)
+string format_full_time(time_t seconds)
+{
+ char buf[50];
+ memset (buf, 0, 50);
+ struct tm ta;
+ if (localtime_r((time_t *)&seconds, &ta) == NULL)
+ memset (&ta, 0, sizeof(struct tm));
+
+ strftime (buf, 49, "%d.%m.%Y %H:%M", &ta);
+ return string(buf);
+}
+
+string format_date(time_t seconds)
{
char buf[50];
memset (buf, 0, 50);
- struct tm *ta = localtime ((time_t *)&seconds);
+ struct tm ta;
+ if (localtime_r((time_t *)&seconds, &ta) == NULL)
+ memset (&ta, 0, sizeof(struct tm));
- strftime (buf, 49, "%d.%m.%Y %H:%M", ta);
+ strftime (buf, 49, "%d.%m.%Y", &ta);
return string(buf);
}
}
}
-std::string output_hour_minute(int hour, int minute, bool h_for_00)
+/**
+ * Split seconds into hours, minutes and seconds
+ * @param [in] daysec Seconds since start of day
+ * @param [out] outhours hours
+ * @param [out] outminutes minutes
+ * @param [out] outseconds seconds
+ */
+void split_daysec(int daysec, int *outhours, int *outminutes, int *outseconds)
+{
+ int hours=daysec/3600;
+ daysec%=3600;
+
+ int minutes=daysec/60;
+ daysec%=60;
+
+ if (outhours)
+ *outhours=hours;
+
+ if (outminutes)
+ *outminutes=minutes;
+
+ if (outseconds)
+ *outseconds=daysec;
+}
+
+std::string output_hour_minute(int hour, int minute, bool h_for_00, int seconds)
{
ostringstream out;
out << '0';
out << hour;
- if (!h_for_00 || minute != 0)
+ if (!h_for_00 || minute != 0 || seconds > 0)
{
out << ':';
if (minute >= 0 && minute < 10)
else
out << 'h';
+ if (seconds > 0)
+ {
+ out << ':';
+ if (seconds > 0 && seconds < 10)
+ out << '0';
+ out << seconds;
+ }
+
return out.str();
}
-WEEK::WEEK(const std::string& daystring)
+string get_month_name(unsigned char month)
{
- int len=daystring.length();
- for (int p=0; p < len; p++)
- {
- char nr[2];
- nr[0]=daystring[p];
- nr[1]=0;
- istringstream c(nr);
- int wnr=-1;
- if (!(c >> wnr) || wnr<0 || wnr >6)
- throw range_error("illegal weekday >"+string(nr)+"< in "+daystring);
-
- days.set(wnr);
+ string rtn;
+ switch(month) {
+ case 1:
+ rtn = i18n("January");
+ break;
+ case 2:
+ rtn = i18n("February");
+ break;
+ case 3:
+ rtn = i18n("March");
+ break;
+ case 4:
+ rtn = i18n("April");
+ break;
+ case 5:
+ rtn = i18n("May");
+ break;
+ case 6:
+ rtn = i18n("June");
+ break;
+ case 7:
+ rtn = i18n("July");
+ break;
+ case 8:
+ rtn = i18n("August");
+ break;
+ case 9:
+ rtn = i18n("September");
+ break;
+ case 10:
+ rtn = i18n("October");
+ break;
+ case 11:
+ rtn = i18n("November");
+ break;
+ case 12:
+ rtn = i18n("December");
+ break;
+ default:
+ {
+ ostringstream out;
+ out << i18n("Illegal month:") << " " << month;
+ rtn = out.str();
+ }
}
+
+ return rtn;
}
-std::string WEEK::get_daystring() const
+
+/*
+** implementaion of Interval
+*/
+
+
+/**
+ * @brief clears the interval (make it empty).
+ */
+void Interval::clear()
{
- ostringstream out;
- for (int i = 0; i < 7; i++)
- if (days[i])
- out << i;
+ m_lower_bound = m_upper_bound = 0;
+} // eo Interval::clear()
+
+
+/**
+ * @brief tests if there is some overlapping with another interval
+ * @param other the other interval
+ * @return @a true if the two intervals have a non empty intersection.
+ */
+bool Interval::intersects(const Interval& other) const
+{
+ return
+ // // other start within this:
+ (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
+ // // other end within this:
+ or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
+ // // other contains this
+ or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
+ ;
+} // eo Interval::intersects(const Interval&)
+
+
+/**
+ * @brief tests if the current interval (fully) contains another one.
+ * @param other the other interval.
+ * @return @a true if the current interval fully contains the other interval.
+ */
+bool Interval::contains(const Interval& other) const
+{
+ return (other.m_lower_bound >= m_lower_bound)
+ and (other.m_upper_bound <= m_upper_bound)
+ ;
+} // eo Interval::contains(const Interval& other) const
+
+
+/*
+** implementation of Intervals:
+*/
+
+
+Intervals::Intervals()
+{
+} // eo Intervals::Intervals
- return out.str();
-}
-std::string WEEK::get_displaystring() const
+void Intervals::clear()
{
- string weekdays_str;
+ m_intervals.clear();
+} // eo Intervals::clear()
+
+/**
+ * @brief tests if one of the intervals of the list intersects with the given interval.
+ * @param other the interval to check for intersection.
+ * @return @a true if there is an intersection.
+ */
+bool Intervals::intersects(const Interval& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( it->intersects(other) )
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::intersects(const Interval&) const
+
- // From Monday to Saturday
- int j;
- for (int i = 1; i < 7; i++)
+/**
+ * @brief tests if we have at least one intersection with another Intervals instance.
+ * @param other the other instance.
+ * @return @a true if there is an intersection.
+ */
+bool Intervals::intersects(const Intervals& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( other.intersects( *it ) )
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::intersects(const Intervals&) const
+
+
+/**
+ * @brief adds a new interval to the list.
+ * @param new_frame the new interval.
+ *
+ * Adds the interval to the list and joins overlapping intervals.
+ *
+ * @internal complexity O(n).
+ */
+void Intervals::add(const Interval& new_frame)
+{
+ if (not new_frame.is_valid() or new_frame.empty())
+ {
+ // well... we will not insert invalid or empty frames!
+ return;
+ }
+ for (IntervalList::iterator it= m_intervals.begin();
+ it != m_intervals.end();
+ ++it)
{
- if (days[i])
+ Interval& current_frame = *it;
+ if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
{
- if (!weekdays_str.empty())
- weekdays_str += ", ";
+ // new_frame begins later than current end; go on:
+ continue;
+ }
+ // at this point: the begin of the new frame is less then the current end.
+ // now let's determine how we can insert the new frame:
- weekdays_str += get_day_display(static_cast<WEEKDAY>(i));
+ if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
+ {
+ // new disjoint frame; insert it before the current frame:
+ m_intervals.insert( it, new_frame );
+ // and we are done.
+ return;
+ }
+ // at this point: the end of the new frame is >= current begin.
+ if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
+ {
+ // the end of the new frame is within our current frame; we need to combine
+ if (new_frame.m_lower_bound < current_frame.m_lower_bound)
+ {
+ // the new interval starts earlier; we need to adjust our current frame:
+ current_frame.m_lower_bound = new_frame.m_lower_bound;
+ current_frame.m_changed = true;
+ }
+ // NOTE no "else" part needed since in that case our current frame already
+ // contains the new one!
- // check if we can group two or more days
- j = i;
- while (days[j] && j < 7)
- j++;
- j--;
+ // we are done:
+ return;
+ }
+ // at this point: end of new frame > end of current frame
+ // so we need to extend the current frame; at least the end.
+ // But we need to deal with intersects of following frames... *sigh*
- // Sunday end of week? j -> 7
- if (j-i > 0 && j == 6 && days[0])
- j++;
+ // first the simple part: let's see if we need to move the start:
+ if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
+ {
+ // yes, we need to move the start:
+ current_frame.m_lower_bound = new_frame.m_lower_bound;
+ current_frame.m_changed= true;
+ }
- if (j-i > 1)
- {
- if (j == 7)
- weekdays_str += "-" + get_day_display(SU);
- else
- weekdays_str += "-" + get_day_display(static_cast<WEEKDAY>(j));
+ // now let's extend the end:
+ current_frame.m_upper_bound = new_frame.m_upper_bound;
+ current_frame.m_changed = true;
- i = j;
+ // well... let's walk through the following frames; looking for more joins...:
+ IntervalList::iterator it2 = it;
+ while( ++(it2=it) != m_intervals.end()
+ and current_frame.m_upper_bound >= it2->m_lower_bound
+ )
+ {
+ Interval next_frame= *it2;
+ if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
+ {
+ // in this case our end is within the next frame.
+ // adjust our end.
+ current_frame.m_upper_bound = next_frame.m_upper_bound;
}
+ // and remove the next frame since the current frame contains it (now):
+ m_intervals.erase(it2);
}
+ // we are done!
+ return;
}
-
- // special: sunday
- if (days[0] && j != 7)
+ // at this point: new frame starts later than the last frame ends
+ // append the new frame:
+ m_intervals.push_back( new_frame );
+} // eo Intervals::add(const Interval&)
+
+
+/**
+ * @brief subtracts a time interval from the list.
+ * @param del_frame the time interval to subtract.
+ *
+ * removes the time interval from the list; cut off parts from or remove existing
+ * intervals if they overlap.
+ *
+ * @internal complexity O(n).
+ */
+void Intervals::sub(const Interval& del_frame)
+{
+ if (not del_frame.is_valid() or del_frame.empty() )
{
- if (!weekdays_str.empty())
- weekdays_str += ", ";
+ return;
+ }
+ for (IntervalList::iterator it= m_intervals.begin();
+ it != m_intervals.end();
+ )
+ {
+ Interval& current_frame = *it;
+ if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
+ {
+ // del_frame begins later than current end; go on:
+ ++it;
+ continue;
+ }
+ // at this point: the begin of the del frame is less then the current end.
+ if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
+ {
+ // end is before our start; nothing to do.
+ return;
+ }
+ // at this point: the end of the del frame is >= current begin.
+ if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
+ {
+ // del frame end point is within our interval.
+ if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
+ {
+ // the del frame is within our interval... we need to split:
+ m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
+ }
+ // adjust start of current frame:
+ if (current_frame.m_lower_bound < del_frame.m_upper_bound)
+ {
+ current_frame.m_lower_bound= del_frame.m_upper_bound;
+ current_frame.m_changed= true;
+ }
+ // and we are done!
+ return;
+ }
+ // at this point the end of the del frame is >= current end
+ if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
+ {
+ // a part of the current interval needs to be preserved..
+ // move the end.
+ current_frame.m_upper_bound= del_frame.m_lower_bound;
+ current_frame.m_changed= true;
+ // and continue with the next interval:
+ ++it;
+ continue;
+ }
+ // at this point; the whole frame needs to be deleted..
+ if ( it == m_intervals.begin())
+ {
+ m_intervals.erase(it);
+ it= m_intervals.begin();
+ }
+ else
+ {
+ IntervalList::iterator it2= it++;
+ m_intervals.erase(it2);
+ }
+ }
+} // eo Intervals::sub(const Interval&)
- weekdays_str += get_day_display(SU);
+
+/**
+ * @brief returns if we contain an interval.
+ * @param other the interval to check.
+ * @return @a true if we cover the given interval, too.
+ */
+bool Intervals::contains(const Interval& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( it->contains( other ))
+ {
+ return true;
+ }
}
+ return false;
+} // eo Intervals::contains(const Interval&) const
+
+
+/**
+ * @brief returns if we contain an exact interval.
+ * @param other the interval to check.
+ * @return @a true if we axactly contains the given interval.
+ *
+ * @note thsi differs from contain in the way, that we return only @a true
+ * iff we have the given interval in our list; not only cover it.
+ */
+bool Intervals::contains_exact(const Interval& other) const
+{
+ for(const_iterator it= begin();
+ it != end();
+ ++it)
+ {
+ if ( *it == other)
+ {
+ return true;
+ }
+ }
+ return false;
+} // eo Intervals::contains_exact(const Interval&)const
+
+
+/**
+ * @brief returns if we contain another interval combination.
+ * @param other the intervals to check.
+ * @return @a true if we cover the given intervals, too.
+ *
+ * @internal we rely on the fact that the lists are sorted and contain
+ * disjoint intervals.
+ *
+ * So this method has a complexity of O(n).
+ */
+bool Intervals::contains(const Intervals& other) const
+{
+ const_iterator my_it= begin();
+ const_iterator other_it= other.begin();
+ while( my_it != end() and other_it!= other.end() )
+ {
+ // seek the first interval which contains the lower bound of the current other interval
+ while (my_it != end()
+ and my_it->m_lower_bound > other_it->m_lower_bound
+ and other_it->m_lower_bound >= my_it->m_upper_bound
+ )
+ {
+ ++my_it;
+ }
+ if (my_it == end())
+ {
+ break;
+ }
+ if (not my_it->contains( *other_it ))
+ {
+ // if we don't contain the current other; we're done:
+ return false;
+ }
+ //else check the next other interval:
+ ++other_it;
+ }
+ return (other_it == other.end());
+} // eo Intervals::contains(const Intervals&) const
+
+
+/**
+ * @brief combines to interval combinates for equality
+ * @param other the other instance.
+ * @return @a true if the other is equal to the current.
+ *
+ * @internal since the lists are sorted, we compare the interval lists.
+ * Thus we have a complexity of O(n).
+ */
+bool Intervals::operator==(const Intervals& other) const
+{
+ // since we keep sorted lists: just compare the lists :-)
+ return m_intervals == other.m_intervals;
+} // eo Intervals::operator==(const Intervals&)
- return weekdays_str;
-}
-std::string WEEK::get_netfilterstring() const
+Intervals& Intervals::operator+=(const Interval& other)
+{
+ add(other);
+ return *this;
+} // eo operator+=(const Interval&)
+
+
+Intervals& Intervals::operator-=(const Interval& other)
+{
+ sub(other);
+ return *this;
+} // eo operator-=(const Interval&)
+
+
+/**
+ * @brief adds the intervals of a second instance to us.
+ * @param other the other instance.
+ * @return self reference (allow chaining).
+ *
+ * @internal since we do simple loops over the other and our intervals
+ * we have a complexity of O(n^2).
+ *
+ * @todo optimize if complexity becomes a problem.
+ */
+Intervals& Intervals::operator+=(const Intervals& other)
{
- string out;
- for (int i = 0; i < 7; i++)
- if (days[i])
+ for(const_iterator it= other.begin();
+ it != other.end();
+ ++it)
+ {
+ add( *it );
+ }
+ return *this;
+} // eo operator+=(const Intervals&)
+
+
+/**
+ * @brief subtracts the intervals of a second instance from us.
+ * @param other the other instance.
+ * @return self reference (allow chaining).
+ *
+ * @internal since we do simple loops over the other and our intervals
+ * we have a complexity of O(n^2).
+ *
+ * @todo optimize if complexity becomes a problem.
+ */
+Intervals& Intervals::operator-=(const Intervals& other)
+{
+ if (&other == this)
+ {
+ m_intervals.clear();
+ }
+ else
+ {
+ for(const_iterator it= other.begin();
+ it != other.end();
+ ++it)
{
- if (!out.empty())
- out+=",";
- out+=get_english_display(static_cast<WEEKDAY>(i));;
+ sub( *it );
}
-
- return out;
-}
+ }
+ return *this;
+} // eo operator-=(const Intervals&)
+
+
+
+/*
+** clock funcs:
+*/
+
+
+/**
+ * @brief fetches the value from the monotonic clock source.
+ * @param[out] seconds the seconds.
+ * @param[out] nano_seconds the nano seconds.
+ * @return @a true if the clock was successfully read.
+ */
+bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
+{
+ struct timespec tp[1];
+ int res= clock_gettime (CLOCK_MONOTONIC, tp);
+ if (0 == res)
+ {
+ seconds= tp->tv_sec;
+ nano_seconds= tp->tv_nsec;
+ }
+ return (res==0);
+} // eo monotonic_clock_gettime(long int&,long int&)
-std::string WEEK::get_day_display(WEEKDAY day)
+
+/**
+ * @brief fetches the value from the monotonic clock source.
+ * @return the time since system start in nanoseconds, 0 if read was unsuccessful
+ */
+long long monotonic_clock_gettime_nano()
{
- string weekday_str;
+ long int seconds;
+ long int nano_seconds;
+ long long nano=0;
- switch (day) {
- case MO:
- weekday_str = i18n("Mon");
- break;
- case TU:
- weekday_str = i18n("Tue");
- break;
- case WE:
- weekday_str = i18n("Wed");
- break;
- case TH:
- weekday_str = i18n("Thu");
- break;
- case FR:
- weekday_str = i18n("Fri");
- break;
- case SA:
- weekday_str = i18n("Sat");
- break;
- case SU:
- weekday_str = i18n("Sun");
- break;
- default:
- break;
+ if (monotonic_clock_gettime(seconds,nano_seconds))
+ {
+ nano=seconds;
+ nano*=1000000000LL;
+ nano+=nano_seconds;
}
- return weekday_str;
+ return nano;
}
-std::string WEEK::get_english_display(WEEKDAY day)
+/**
+ * @brief fetches the value from the monotonic clock source.
+ * @param[out] seconds the seconds.
+ * @param[out] nano_seconds the nano seconds.
+ * @return @a true if the clock was successfully read.
+ */
+bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
{
- string weekday_str;
+ struct timespec tp[1];
+ int res= clock_gettime(CLOCK_REALTIME, tp);
+ if (0 == res)
+ {
+ seconds= tp->tv_sec;
+ nano_seconds= tp->tv_nsec;
+ }
+ return (res==0);
+} // eo realtime_clock_gettime(long int&,long int&)
- switch (day) {
- case MO:
- weekday_str = "Mon";
- break;
- case TU:
- weekday_str = "Tue";
- break;
- case WE:
- weekday_str = "Wed";
- break;
- case TH:
- weekday_str = "Thu";
- break;
- case FR:
- weekday_str = "Fri";
- break;
- case SA:
- weekday_str = "Sat";
- break;
- case SU:
- weekday_str = "Sun";
- break;
- default:
- break;
+
+namespace I2n {
+
+namespace clock {
+
+ namespace {
+
+ static inline clockid_t
+ clockid_of_flags (const enum type::id id,
+ const enum type::variant var) NOEXCEPT
+ {
+ clockid_t cid = CLOCK_MONOTONIC_COARSE;
+
+ switch (id) {
+
+ default:
+ case type::mono: {
+ switch (var) {
+ default: {
+ break;
+ }
+ case type::raw: {
+ cid = CLOCK_MONOTONIC_RAW;
+ break;
+ }
+ case type::exact: {
+ cid = CLOCK_MONOTONIC;
+ break;
+ }
+ }
+ break;
+ }
+
+ case type::real: {
+ if (var == type::exact) {
+ cid = CLOCK_REALTIME;
+ } else {
+ cid = CLOCK_REALTIME_COARSE;
+ }
+ break;
+ }
+
+ case type::boot: {
+ if (var & type::exact) {
+ cid = CLOCK_BOOTTIME;
+ }
+ break;
+ }
+
+ case type::cpu: {
+ if (var == type::thread) {
+ cid = CLOCK_THREAD_CPUTIME_ID;
+ } else {
+ cid = CLOCK_PROCESS_CPUTIME_ID;
+ }
+ break;
+ }
+ } /* [switch id] */
+
+ return cid;
+ }
+
+ static const struct timespec zero_time = { 0, 0 };
+
+ } /* [namespace] */
+
+ Time::Time (const enum type::id id,
+ const enum type::variant var) NOEXCEPT
+ : value (zero_time)
+ , id (id)
+ , variant (var)
+ , err (0)
+ { }
+
+ int64_t
+ Time::as_nanosec (void) const NOEXCEPT
+ {
+ return int64_t (this->value.tv_sec) * TIME_CONST_FACTOR_NANO
+ + this->value.tv_nsec;
}
- return weekday_str;
-}
+ long
+ Time::as_nanosec_L (void) const NOEXCEPT /* likely to overflow */
+ { return static_cast<long>(this->as_nanosec ()); }
+
+ Time &
+ Time::operator= (Time t2) NOEXCEPT
+ {
+ this->swap (t2);
+
+ return *this;
+ }
+
+ Time &
+ Time::operator= (struct timespec ts) NOEXCEPT
+ {
+ std::swap (this->value, ts);
+ this->id = clock::type::mono;
+ this->variant = clock::type::dflt;
+ this->err = 0;
+
+ return *this;
+ }
+
+ void
+ Time::unset (void) NOEXCEPT
+ { this->value = zero_time; }
+
+ bool
+ Time::set (void) NOEXCEPT
+ {
+ struct timespec now;
+
+ errno = 0;
+ if (clock_gettime (clockid_of_flags (this->id, this->variant), &now)
+ == -1)
+ {
+ this->err = errno;
+ this->unset ();
+
+ return false;
+ }
+ this->err = 0;
+ this->value = now;
+
+ return true;
+ }
+
+ Time &
+ Time::add (const time_t sec, const long nsec) NOEXCEPT
+ {
+ this->value.tv_sec += sec;
+ this->value.tv_nsec += nsec;
+
+ this->carry_nsec ();
+
+ return *this;
+ }
+
+ Time &
+ Time::subtract (const time_t sec, const long nsec) NOEXCEPT
+ {
+ this->value.tv_sec -= sec;
+ this->value.tv_nsec -= nsec;
+
+ this->carry_nsec ();
+
+ return *this;
+ }
+
+ Time &
+ Time::scale (const time_t factor) NOEXCEPT
+ {
+ this->value.tv_sec *= factor;
+ this->value.tv_nsec *= factor;
+
+ this->carry_nsec ();
+
+ return *this;
+ }
+
+ boost::optional<Time>
+ now (const enum type::id id, const enum type::variant var) NOEXCEPT
+ {
+ Time ret (id, var);
+
+ if (!ret.set ()) {
+ return boost::none;
+ }
+
+ return ret;
+ }
+
+ Time
+ zero (const enum type::id id, const enum type::variant var) NOEXCEPT
+ { return Time (id, var); }
+
+ int
+ compare (const Time &t1, const Time &t2) NOEXCEPT
+ {
+ if (t1.value.tv_sec < t2.value.tv_sec) {
+ return -1;
+ }
+
+ if (t1.value.tv_sec > t2.value.tv_sec) {
+ return 1;
+ }
+
+ if (t1.value.tv_nsec < t2.value.tv_nsec) {
+ return -1;
+ }
+
+ if (t1.value.tv_nsec > t2.value.tv_nsec) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+} /* [namespace clock] */
+
+} /* [namespace I2n] */
+