2 * @brief time related functions.
4 * @copyright Copyright © 2001-2008 by Intra2net AG
6 * @contact info@intra2net.com
23 #include <sys/timeb.h>
24 #include <sys/syscall.h>
26 #include <timefunc.hxx>
30 // define missing POSIX.1b constants...
32 #ifndef CLOCK_REALTIME
33 #define CLOCK_REALTIME 0
35 #ifndef CLOCK_MONOTONIC
36 #define CLOCK_MONOTONIC 1
43 double prec_time(void)
50 ret=tb.time+(static_cast<float>(tb.millitm)/1000);
55 // converts ISO-DATE: 2003-06-13
56 int date_to_seconds(const std::string &date)
58 int rtn = -1, year = -1, month = -1, day = -1;
60 string::size_type pos = date.find("-");
61 if (pos == string::npos)
64 istringstream in(string(date,0,pos));
68 string dstr(date, pos+1);
69 if ((pos = dstr.find("-")) == string::npos)
73 in.str(string(dstr, 0, pos));
78 in.str(string(dstr, pos+1));
81 if (year < 0 || month == -1 || day == -1)
85 bzero (&tm_struct, sizeof(struct tm));
86 tm_struct.tm_year = year;
87 tm_struct.tm_mon = month;
88 tm_struct.tm_mday = day;
89 tm_struct.tm_isdst = -1;
91 rtn = mktime (&tm_struct);
95 string make_nice_time(int seconds)
99 int days=seconds/86400;
103 split_daysec(seconds,&hours,&minutes,&seconds);
106 out << i18n("1 day") << ", ";
108 out << days << ' ' << i18n("days") << ", ";
111 out << setw(2) << hours << ':' << setw(2) << minutes << ':' << setw(2) << seconds;
116 string format_full_time(int seconds)
120 struct tm *ta = localtime ((time_t *)&seconds);
122 strftime (buf, 49, "%d.%m.%Y %H:%M", ta);
126 void seconds_to_hour_minute(int seconds, int *hour, int *minute)
130 while (seconds >= 3600) {
136 if (minute != NULL) {
138 while (seconds >= 60) {
146 * Split seconds into hours, minutes and seconds
147 * @param [in] daysec Seconds since start of day
148 * @param [out] outhours hours
149 * @param [out] outminutes minutes
150 * @param [out] outseconds seconds
152 void split_daysec(int daysec, int *outhours, int *outminutes, int *outseconds)
154 int hours=daysec/3600;
157 int minutes=daysec/60;
170 std::string output_hour_minute(int hour, int minute, bool h_for_00, int seconds)
174 if (hour >= 0 && hour < 10)
178 if (!h_for_00 || minute != 0 || seconds > 0)
181 if (minute >= 0 && minute < 10)
191 if (seconds > 0 && seconds < 10)
199 string get_month_name(unsigned char month)
204 rtn = i18n("January");
207 rtn = i18n("February");
225 rtn = i18n("August");
228 rtn = i18n("September");
231 rtn = i18n("October");
234 rtn = i18n("November");
237 rtn = i18n("December");
242 out << i18n("Illegal month:") << " " << month;
252 ** implementaion of Interval
257 * @brief clears the interval (make it empty).
259 void Interval::clear()
261 m_lower_bound = m_upper_bound = 0;
262 } // eo Interval::clear()
266 * @brief tests if there is some overlapping with another interval
267 * @param other the other interval
268 * @return @a true if the two intervals have a non empty intersection.
270 bool Interval::intersects(const Interval& other) const
273 // // other start within this:
274 (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
275 // // other end within this:
276 or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
277 // // other contains this
278 or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
280 } // eo Interval::intersects(const Interval&)
284 * @brief tests if the current interval (fully) contains another one.
285 * @param other the other interval.
286 * @return @a true if the current interval fully contains the other interval.
288 bool Interval::contains(const Interval& other) const
290 return (other.m_lower_bound >= m_lower_bound)
291 and (other.m_upper_bound <= m_upper_bound)
293 } // eo Interval::contains(const Interval& other) const
297 ** implementation of Intervals:
301 Intervals::Intervals()
303 } // eo Intervals::Intervals
306 void Intervals::clear()
309 } // eo Intervals::clear()
312 * @brief tests if one of the intervals of the list intersects with the given interval.
313 * @param other the interval to check for intersection.
314 * @return @a true if there is an intersection.
316 bool Intervals::intersects(const Interval& other) const
318 for(const_iterator it= begin();
322 if ( it->intersects(other) )
328 } // eo Intervals::intersects(const Interval&) const
332 * @brief tests if we have at least one intersection with another Intervals instance.
333 * @param other the other instance.
334 * @return @a true if there is an intersection.
336 bool Intervals::intersects(const Intervals& other) const
338 for(const_iterator it= begin();
342 if ( other.intersects( *it ) )
348 } // eo Intervals::intersects(const Intervals&) const
352 * @brief adds a new interval to the list.
353 * @param new_frame the new interval.
355 * Adds the interval to the list and joins overlapping intervals.
357 * @internal complexity O(n).
359 void Intervals::add(const Interval& new_frame)
361 if (not new_frame.is_valid() or new_frame.empty())
363 // well... we will not insert invalid or empty frames!
366 for (IntervalList::iterator it= m_intervals.begin();
367 it != m_intervals.end();
370 Interval& current_frame = *it;
371 if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
373 // new_frame begins later than current end; go on:
376 // at this point: the begin of the new frame is less then the current end.
377 // now let's determine how we can insert the new frame:
379 if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
381 // new disjoint frame; insert it before the current frame:
382 m_intervals.insert( it, new_frame );
386 // at this point: the end of the new frame is >= current begin.
387 if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
389 // the end of the new frame is within our current frame; we need to combine
390 if (new_frame.m_lower_bound < current_frame.m_lower_bound)
392 // the new interval starts earlier; we need to adjust our current frame:
393 current_frame.m_lower_bound = new_frame.m_lower_bound;
394 current_frame.m_changed = true;
396 // NOTE no "else" part needed since in that case our current frame already
397 // contains the new one!
402 // at this point: end of new frame > end of current frame
403 // so we need to extend the current frame; at least the end.
404 // But we need to deal with intersects of following frames... *sigh*
406 // first the simple part: let's see if we need to move the start:
407 if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
409 // yes, we need to move the start:
410 current_frame.m_lower_bound = new_frame.m_lower_bound;
411 current_frame.m_changed= true;
414 // now let's extend the end:
415 current_frame.m_upper_bound = new_frame.m_upper_bound;
416 current_frame.m_changed = true;
418 // well... let's walk through the following frames; looking for more joins...:
419 IntervalList::iterator it2 = it;
420 while( ++(it2=it) != m_intervals.end()
421 and current_frame.m_upper_bound >= it2->m_lower_bound
424 Interval next_frame= *it2;
425 if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
427 // in this case our end is within the next frame.
429 current_frame.m_upper_bound = next_frame.m_upper_bound;
431 // and remove the next frame since the current frame contains it (now):
432 m_intervals.erase(it2);
437 // at this point: new frame starts later than the last frame ends
438 // append the new frame:
439 m_intervals.push_back( new_frame );
440 } // eo Intervals::add(const Interval&)
444 * @brief subtracts a time interval from the list.
445 * @param del_frame the time interval to subtract.
447 * removes the time interval from the list; cut off parts from or remove existing
448 * intervals if they overlap.
450 * @internal complexity O(n).
452 void Intervals::sub(const Interval& del_frame)
454 if (not del_frame.is_valid() or del_frame.empty() )
458 for (IntervalList::iterator it= m_intervals.begin();
459 it != m_intervals.end();
462 Interval& current_frame = *it;
463 if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
465 // del_frame begins later than current end; go on:
469 // at this point: the begin of the del frame is less then the current end.
470 if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
472 // end is before our start; nothing to do.
475 // at this point: the end of the del frame is >= current begin.
476 if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
478 // del frame end point is within our interval.
479 if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
481 // the del frame is within our interval... we need to split:
482 m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
484 // adjust start of current frame:
485 if (current_frame.m_lower_bound < del_frame.m_upper_bound)
487 current_frame.m_lower_bound= del_frame.m_upper_bound;
488 current_frame.m_changed= true;
493 // at this point the end of the del frame is >= current end
494 if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
496 // a part of the current interval needs to be preserved..
498 current_frame.m_upper_bound= del_frame.m_lower_bound;
499 current_frame.m_changed= true;
500 // and continue with the next interval:
504 // at this point; the whole frame needs to be deleted..
505 if ( it == m_intervals.begin())
507 m_intervals.erase(it);
508 it= m_intervals.begin();
512 IntervalList::iterator it2= it++;
513 m_intervals.erase(it2);
516 } // eo Intervals::sub(const Interval&)
520 * @brief returns if we contain an interval.
521 * @param other the interval to check.
522 * @return @a true if we cover the given interval, too.
524 bool Intervals::contains(const Interval& other) const
526 for(const_iterator it= begin();
530 if ( it->contains( other ))
536 } // eo Intervals::contains(const Interval&) const
540 * @brief returns if we contain an exact interval.
541 * @param other the interval to check.
542 * @return @a true if we axactly contains the given interval.
544 * @note thsi differs from contain in the way, that we return only @a true
545 * iff we have the given interval in our list; not only cover it.
547 bool Intervals::contains_exact(const Interval& other) const
549 for(const_iterator it= begin();
559 } // eo Intervals::contains_exact(const Interval&)const
563 * @brief returns if we contain another interval combination.
564 * @param other the intervals to check.
565 * @return @a true if we cover the given intervals, too.
567 * @internal we rely on the fact that the lists are sorted and contain
568 * disjoint intervals.
570 * So this method has a complexity of O(n).
572 bool Intervals::contains(const Intervals& other) const
574 const_iterator my_it= begin();
575 const_iterator other_it= other.begin();
576 while( my_it != end() and other_it!= other.end() )
578 // seek the first interval which contains the lower bound of the current other interval
579 while (my_it != end()
580 and my_it->m_lower_bound > other_it->m_lower_bound
581 and other_it->m_lower_bound >= my_it->m_upper_bound
590 if (not my_it->contains( *other_it ))
592 // if we don't contain the current other; we're done:
595 //else check the next other interval:
598 return (other_it == other.end());
599 } // eo Intervals::contains(const Intervals&) const
603 * @brief combines to interval combinates for equality
604 * @param other the other instance.
605 * @return @a true if the other is equal to the current.
607 * @internal since the lists are sorted, we compare the interval lists.
608 * Thus we have a complexity of O(n).
610 bool Intervals::operator==(const Intervals& other) const
612 // since we keep sorted lists: just compare the lists :-)
613 return m_intervals == other.m_intervals;
614 } // eo Intervals::operator==(const Intervals&)
617 Intervals& Intervals::operator+=(const Interval& other)
621 } // eo operator+=(const Interval&)
624 Intervals& Intervals::operator-=(const Interval& other)
628 } // eo operator-=(const Interval&)
632 * @brief adds the intervals of a second instance to us.
633 * @param other the other instance.
634 * @return self reference (allow chaining).
636 * @internal since we do simple loops over the other and our intervals
637 * we have a complexity of O(n^2).
639 * @todo optimize if complexity becomes a problem.
641 Intervals& Intervals::operator+=(const Intervals& other)
643 for(const_iterator it= other.begin();
650 } // eo operator+=(const Intervals&)
654 * @brief subtracts the intervals of a second instance from us.
655 * @param other the other instance.
656 * @return self reference (allow chaining).
658 * @internal since we do simple loops over the other and our intervals
659 * we have a complexity of O(n^2).
661 * @todo optimize if complexity becomes a problem.
663 Intervals& Intervals::operator-=(const Intervals& other)
671 for(const_iterator it= other.begin();
679 } // eo operator-=(const Intervals&)
689 * @brief fetches the value from the monotonic clock source.
690 * @param[out] seconds the seconds.
691 * @param[out] nano_seconds the nano seconds.
692 * @return @a true if the clock was successfully read.
694 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
696 struct timespec tp[1];
697 int res= ::syscall(__NR_clock_gettime, CLOCK_MONOTONIC, tp);
701 nano_seconds= tp->tv_nsec;
704 } // eo monotonic_clock_gettime(long int&,long int&)
708 * @brief fetches the value from the monotonic clock source.
709 * @return the time since system start in nanoseconds, 0 if read was unsuccessful
711 long long monotonic_clock_gettime_nano()
714 long int nano_seconds;
717 if (monotonic_clock_gettime(seconds,nano_seconds))
728 * @brief fetches the value from the monotonic clock source.
729 * @param[out] seconds the seconds.
730 * @param[out] nano_seconds the nano seconds.
731 * @return @a true if the clock was successfully read.
733 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
735 struct timespec tp[1];
736 int res= ::syscall(__NR_clock_gettime, CLOCK_REALTIME, tp);
740 nano_seconds= tp->tv_nsec;
743 } // eo realtime_clock_gettime(long int&,long int&)