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
39 #include <sys/timeb.h>
40 #include <sys/syscall.h>
42 #include <timefunc.hxx>
46 // define missing POSIX.1b constants...
48 #ifndef CLOCK_REALTIME
49 #define CLOCK_REALTIME 0
51 #ifndef CLOCK_MONOTONIC
52 #define CLOCK_MONOTONIC 1
59 double prec_time(void)
66 ret=tb.time+(static_cast<float>(tb.millitm)/1000);
71 // converts ISO-DATE: 2003-06-13
72 int date_to_seconds(const std::string &date)
74 int rtn = -1, year = -1, month = -1, day = -1;
76 string::size_type pos = date.find("-");
77 if (pos == string::npos)
80 istringstream in(string(date,0,pos));
84 string dstr(date, pos+1);
85 if ((pos = dstr.find("-")) == string::npos)
89 in.str(string(dstr, 0, pos));
94 in.str(string(dstr, pos+1));
97 if (year < 0 || month == -1 || day == -1)
101 memset(&tm_struct, 0, sizeof(struct tm));
102 tm_struct.tm_year = year;
103 tm_struct.tm_mon = month;
104 tm_struct.tm_mday = day;
105 tm_struct.tm_isdst = -1;
107 rtn = mktime (&tm_struct);
111 string make_nice_time(int seconds)
115 int days=seconds/86400;
119 split_daysec(seconds,&hours,&minutes,&seconds);
122 out << i18n("1 day") << ", ";
124 out << days << ' ' << i18n("days") << ", ";
127 out << setw(2) << hours << ':' << setw(2) << minutes << ':' << setw(2) << seconds;
132 string format_full_time(time_t seconds)
137 if (localtime_r((time_t *)&seconds, &ta) == NULL)
138 memset (&ta, 0, sizeof(struct tm));
140 strftime (buf, 49, "%d.%m.%Y %H:%M", &ta);
144 void seconds_to_hour_minute(int seconds, int *hour, int *minute)
148 while (seconds >= 3600) {
154 if (minute != NULL) {
156 while (seconds >= 60) {
164 * Split seconds into hours, minutes and seconds
165 * @param [in] daysec Seconds since start of day
166 * @param [out] outhours hours
167 * @param [out] outminutes minutes
168 * @param [out] outseconds seconds
170 void split_daysec(int daysec, int *outhours, int *outminutes, int *outseconds)
172 int hours=daysec/3600;
175 int minutes=daysec/60;
188 std::string output_hour_minute(int hour, int minute, bool h_for_00, int seconds)
192 if (hour >= 0 && hour < 10)
196 if (!h_for_00 || minute != 0 || seconds > 0)
199 if (minute >= 0 && minute < 10)
209 if (seconds > 0 && seconds < 10)
217 string get_month_name(unsigned char month)
222 rtn = i18n("January");
225 rtn = i18n("February");
243 rtn = i18n("August");
246 rtn = i18n("September");
249 rtn = i18n("October");
252 rtn = i18n("November");
255 rtn = i18n("December");
260 out << i18n("Illegal month:") << " " << month;
270 ** implementaion of Interval
275 * @brief clears the interval (make it empty).
277 void Interval::clear()
279 m_lower_bound = m_upper_bound = 0;
280 } // eo Interval::clear()
284 * @brief tests if there is some overlapping with another interval
285 * @param other the other interval
286 * @return @a true if the two intervals have a non empty intersection.
288 bool Interval::intersects(const Interval& other) const
291 // // other start within this:
292 (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
293 // // other end within this:
294 or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
295 // // other contains this
296 or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
298 } // eo Interval::intersects(const Interval&)
302 * @brief tests if the current interval (fully) contains another one.
303 * @param other the other interval.
304 * @return @a true if the current interval fully contains the other interval.
306 bool Interval::contains(const Interval& other) const
308 return (other.m_lower_bound >= m_lower_bound)
309 and (other.m_upper_bound <= m_upper_bound)
311 } // eo Interval::contains(const Interval& other) const
315 ** implementation of Intervals:
319 Intervals::Intervals()
321 } // eo Intervals::Intervals
324 void Intervals::clear()
327 } // eo Intervals::clear()
330 * @brief tests if one of the intervals of the list intersects with the given interval.
331 * @param other the interval to check for intersection.
332 * @return @a true if there is an intersection.
334 bool Intervals::intersects(const Interval& other) const
336 for(const_iterator it= begin();
340 if ( it->intersects(other) )
346 } // eo Intervals::intersects(const Interval&) const
350 * @brief tests if we have at least one intersection with another Intervals instance.
351 * @param other the other instance.
352 * @return @a true if there is an intersection.
354 bool Intervals::intersects(const Intervals& other) const
356 for(const_iterator it= begin();
360 if ( other.intersects( *it ) )
366 } // eo Intervals::intersects(const Intervals&) const
370 * @brief adds a new interval to the list.
371 * @param new_frame the new interval.
373 * Adds the interval to the list and joins overlapping intervals.
375 * @internal complexity O(n).
377 void Intervals::add(const Interval& new_frame)
379 if (not new_frame.is_valid() or new_frame.empty())
381 // well... we will not insert invalid or empty frames!
384 for (IntervalList::iterator it= m_intervals.begin();
385 it != m_intervals.end();
388 Interval& current_frame = *it;
389 if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
391 // new_frame begins later than current end; go on:
394 // at this point: the begin of the new frame is less then the current end.
395 // now let's determine how we can insert the new frame:
397 if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
399 // new disjoint frame; insert it before the current frame:
400 m_intervals.insert( it, new_frame );
404 // at this point: the end of the new frame is >= current begin.
405 if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
407 // the end of the new frame is within our current frame; we need to combine
408 if (new_frame.m_lower_bound < current_frame.m_lower_bound)
410 // the new interval starts earlier; we need to adjust our current frame:
411 current_frame.m_lower_bound = new_frame.m_lower_bound;
412 current_frame.m_changed = true;
414 // NOTE no "else" part needed since in that case our current frame already
415 // contains the new one!
420 // at this point: end of new frame > end of current frame
421 // so we need to extend the current frame; at least the end.
422 // But we need to deal with intersects of following frames... *sigh*
424 // first the simple part: let's see if we need to move the start:
425 if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
427 // yes, we need to move the start:
428 current_frame.m_lower_bound = new_frame.m_lower_bound;
429 current_frame.m_changed= true;
432 // now let's extend the end:
433 current_frame.m_upper_bound = new_frame.m_upper_bound;
434 current_frame.m_changed = true;
436 // well... let's walk through the following frames; looking for more joins...:
437 IntervalList::iterator it2 = it;
438 while( ++(it2=it) != m_intervals.end()
439 and current_frame.m_upper_bound >= it2->m_lower_bound
442 Interval next_frame= *it2;
443 if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
445 // in this case our end is within the next frame.
447 current_frame.m_upper_bound = next_frame.m_upper_bound;
449 // and remove the next frame since the current frame contains it (now):
450 m_intervals.erase(it2);
455 // at this point: new frame starts later than the last frame ends
456 // append the new frame:
457 m_intervals.push_back( new_frame );
458 } // eo Intervals::add(const Interval&)
462 * @brief subtracts a time interval from the list.
463 * @param del_frame the time interval to subtract.
465 * removes the time interval from the list; cut off parts from or remove existing
466 * intervals if they overlap.
468 * @internal complexity O(n).
470 void Intervals::sub(const Interval& del_frame)
472 if (not del_frame.is_valid() or del_frame.empty() )
476 for (IntervalList::iterator it= m_intervals.begin();
477 it != m_intervals.end();
480 Interval& current_frame = *it;
481 if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
483 // del_frame begins later than current end; go on:
487 // at this point: the begin of the del frame is less then the current end.
488 if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
490 // end is before our start; nothing to do.
493 // at this point: the end of the del frame is >= current begin.
494 if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
496 // del frame end point is within our interval.
497 if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
499 // the del frame is within our interval... we need to split:
500 m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
502 // adjust start of current frame:
503 if (current_frame.m_lower_bound < del_frame.m_upper_bound)
505 current_frame.m_lower_bound= del_frame.m_upper_bound;
506 current_frame.m_changed= true;
511 // at this point the end of the del frame is >= current end
512 if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
514 // a part of the current interval needs to be preserved..
516 current_frame.m_upper_bound= del_frame.m_lower_bound;
517 current_frame.m_changed= true;
518 // and continue with the next interval:
522 // at this point; the whole frame needs to be deleted..
523 if ( it == m_intervals.begin())
525 m_intervals.erase(it);
526 it= m_intervals.begin();
530 IntervalList::iterator it2= it++;
531 m_intervals.erase(it2);
534 } // eo Intervals::sub(const Interval&)
538 * @brief returns if we contain an interval.
539 * @param other the interval to check.
540 * @return @a true if we cover the given interval, too.
542 bool Intervals::contains(const Interval& other) const
544 for(const_iterator it= begin();
548 if ( it->contains( other ))
554 } // eo Intervals::contains(const Interval&) const
558 * @brief returns if we contain an exact interval.
559 * @param other the interval to check.
560 * @return @a true if we axactly contains the given interval.
562 * @note thsi differs from contain in the way, that we return only @a true
563 * iff we have the given interval in our list; not only cover it.
565 bool Intervals::contains_exact(const Interval& other) const
567 for(const_iterator it= begin();
577 } // eo Intervals::contains_exact(const Interval&)const
581 * @brief returns if we contain another interval combination.
582 * @param other the intervals to check.
583 * @return @a true if we cover the given intervals, too.
585 * @internal we rely on the fact that the lists are sorted and contain
586 * disjoint intervals.
588 * So this method has a complexity of O(n).
590 bool Intervals::contains(const Intervals& other) const
592 const_iterator my_it= begin();
593 const_iterator other_it= other.begin();
594 while( my_it != end() and other_it!= other.end() )
596 // seek the first interval which contains the lower bound of the current other interval
597 while (my_it != end()
598 and my_it->m_lower_bound > other_it->m_lower_bound
599 and other_it->m_lower_bound >= my_it->m_upper_bound
608 if (not my_it->contains( *other_it ))
610 // if we don't contain the current other; we're done:
613 //else check the next other interval:
616 return (other_it == other.end());
617 } // eo Intervals::contains(const Intervals&) const
621 * @brief combines to interval combinates for equality
622 * @param other the other instance.
623 * @return @a true if the other is equal to the current.
625 * @internal since the lists are sorted, we compare the interval lists.
626 * Thus we have a complexity of O(n).
628 bool Intervals::operator==(const Intervals& other) const
630 // since we keep sorted lists: just compare the lists :-)
631 return m_intervals == other.m_intervals;
632 } // eo Intervals::operator==(const Intervals&)
635 Intervals& Intervals::operator+=(const Interval& other)
639 } // eo operator+=(const Interval&)
642 Intervals& Intervals::operator-=(const Interval& other)
646 } // eo operator-=(const Interval&)
650 * @brief adds the intervals of a second instance to us.
651 * @param other the other instance.
652 * @return self reference (allow chaining).
654 * @internal since we do simple loops over the other and our intervals
655 * we have a complexity of O(n^2).
657 * @todo optimize if complexity becomes a problem.
659 Intervals& Intervals::operator+=(const Intervals& other)
661 for(const_iterator it= other.begin();
668 } // eo operator+=(const Intervals&)
672 * @brief subtracts the intervals of a second instance from us.
673 * @param other the other instance.
674 * @return self reference (allow chaining).
676 * @internal since we do simple loops over the other and our intervals
677 * we have a complexity of O(n^2).
679 * @todo optimize if complexity becomes a problem.
681 Intervals& Intervals::operator-=(const Intervals& other)
689 for(const_iterator it= other.begin();
697 } // eo operator-=(const Intervals&)
707 * @brief fetches the value from the monotonic clock source.
708 * @param[out] seconds the seconds.
709 * @param[out] nano_seconds the nano seconds.
710 * @return @a true if the clock was successfully read.
712 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
714 struct timespec tp[1];
715 int res= ::syscall(__NR_clock_gettime, CLOCK_MONOTONIC, tp);
719 nano_seconds= tp->tv_nsec;
722 } // eo monotonic_clock_gettime(long int&,long int&)
726 * @brief fetches the value from the monotonic clock source.
727 * @return the time since system start in nanoseconds, 0 if read was unsuccessful
729 long long monotonic_clock_gettime_nano()
732 long int nano_seconds;
735 if (monotonic_clock_gettime(seconds,nano_seconds))
746 * @brief fetches the value from the monotonic clock source.
747 * @param[out] seconds the seconds.
748 * @param[out] nano_seconds the nano seconds.
749 * @return @a true if the clock was successfully read.
751 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
753 struct timespec tp[1];
754 int res= ::syscall(__NR_clock_gettime, CLOCK_REALTIME, tp);
758 nano_seconds= tp->tv_nsec;
761 } // eo realtime_clock_gettime(long int&,long int&)