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;
102 int hours=seconds/3600;
105 int minutes=seconds/60;
109 out << i18n("1 day") << ", ";
111 out << days << ' ' << i18n("days") << ", ";
114 out << setw(2) << hours << ':' << setw(2) << minutes << ':' << setw(2) << seconds;
119 string format_full_time(int seconds)
123 struct tm *ta = localtime ((time_t *)&seconds);
125 strftime (buf, 49, "%d.%m.%Y %H:%M", ta);
129 void seconds_to_hour_minute(int seconds, int *hour, int *minute)
133 while (seconds >= 3600) {
139 if (minute != NULL) {
141 while (seconds >= 60) {
148 std::string output_hour_minute(int hour, int minute, bool h_for_00)
152 if (hour >= 0 && hour < 10)
156 if (!h_for_00 || minute != 0)
159 if (minute >= 0 && minute < 10)
169 string get_month_name(unsigned char month)
174 rtn = i18n("January");
177 rtn = i18n("February");
195 rtn = i18n("August");
198 rtn = i18n("September");
201 rtn = i18n("October");
204 rtn = i18n("November");
207 rtn = i18n("December");
212 out << i18n("Illegal month:") << " " << month;
222 ** implementaion of Interval
227 * @brief clears the interval (make it empty).
229 void Interval::clear()
231 m_lower_bound = m_upper_bound = 0;
232 } // eo Interval::clear()
236 * @brief tests if there is some overlapping with another interval
237 * @param other the other interval
238 * @return @a true if the two intervals have a non empty intersection.
240 bool Interval::intersects(const Interval& other) const
243 // // other start within this:
244 (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
245 // // other end within this:
246 or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
247 // // other contains this
248 or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
250 } // eo Interval::intersects(const Interval&)
254 * @brief tests if the current interval (fully) contains another one.
255 * @param other the other interval.
256 * @return @a true if the current interval fully contains the other interval.
258 bool Interval::contains(const Interval& other) const
260 return (other.m_lower_bound >= m_lower_bound)
261 and (other.m_upper_bound <= m_upper_bound)
263 } // eo Interval::contains(const Interval& other) const
267 ** implementation of Intervals:
271 Intervals::Intervals()
273 } // eo Intervals::Intervals
276 void Intervals::clear()
279 } // eo Intervals::clear()
282 * @brief tests if one of the intervals of the list intersects with the given interval.
283 * @param other the interval to check for intersection.
284 * @return @a true if there is an intersection.
286 bool Intervals::intersects(const Interval& other) const
288 for(const_iterator it= begin();
292 if ( it->intersects(other) )
298 } // eo Intervals::intersects(const Interval&) const
302 * @brief tests if we have at least one intersection with another Intervals instance.
303 * @param other the other instance.
304 * @return @a true if there is an intersection.
306 bool Intervals::intersects(const Intervals& other) const
308 for(const_iterator it= begin();
312 if ( other.intersects( *it ) )
318 } // eo Intervals::intersects(const Intervals&) const
322 * @brief adds a new interval to the list.
323 * @param new_frame the new interval.
325 * Adds the interval to the list and joins overlapping intervals.
327 * @internal complexity O(n).
329 void Intervals::add(const Interval& new_frame)
331 if (not new_frame.is_valid() or new_frame.empty())
333 // well... we will not insert invalid or empty frames!
336 for (IntervalList::iterator it= m_intervals.begin();
337 it != m_intervals.end();
340 Interval& current_frame = *it;
341 if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
343 // new_frame begins later than current end; go on:
346 // at this point: the begin of the new frame is less then the current end.
347 // now let's determine how we can insert the new frame:
349 if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
351 // new disjoint frame; insert it before the current frame:
352 m_intervals.insert( it, new_frame );
356 // at this point: the end of the new frame is >= current begin.
357 if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
359 // the end of the new frame is within our current frame; we need to combine
360 if (new_frame.m_lower_bound < current_frame.m_lower_bound)
362 // the new interval starts earlier; we need to adjust our current frame:
363 current_frame.m_lower_bound = new_frame.m_lower_bound;
364 current_frame.m_changed = true;
366 // NOTE no "else" part needed since in that case our current frame already
367 // contains the new one!
372 // at this point: end of new frame > end of current frame
373 // so we need to extend the current frame; at least the end.
374 // But we need to deal with intersects of following frames... *sigh*
376 // first the simple part: let's see if we need to move the start:
377 if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
379 // yes, we need to move the start:
380 current_frame.m_lower_bound = new_frame.m_lower_bound;
381 current_frame.m_changed= true;
384 // now let's extend the end:
385 current_frame.m_upper_bound = new_frame.m_upper_bound;
386 current_frame.m_changed = true;
388 // well... let's walk through the following frames; looking for more joins...:
389 IntervalList::iterator it2 = it;
390 while( ++(it2=it) != m_intervals.end()
391 and current_frame.m_upper_bound >= it2->m_lower_bound
394 Interval next_frame= *it2;
395 if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
397 // in this case our end is within the next frame.
399 current_frame.m_upper_bound = next_frame.m_upper_bound;
401 // and remove the next frame since the current frame contains it (now):
402 m_intervals.erase(it2);
407 // at this point: new frame starts later than the last frame ends
408 // append the new frame:
409 m_intervals.push_back( new_frame );
410 } // eo Intervals::add(const Interval&)
414 * @brief subtracts a time interval from the list.
415 * @param del_frame the time interval to subtract.
417 * removes the time interval from the list; cut off parts from or remove existing
418 * intervals if they overlap.
420 * @internal complexity O(n).
422 void Intervals::sub(const Interval& del_frame)
424 if (not del_frame.is_valid() or del_frame.empty() )
428 for (IntervalList::iterator it= m_intervals.begin();
429 it != m_intervals.end();
432 Interval& current_frame = *it;
433 if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
435 // del_frame begins later than current end; go on:
439 // at this point: the begin of the del frame is less then the current end.
440 if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
442 // end is before our start; nothing to do.
445 // at this point: the end of the del frame is >= current begin.
446 if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
448 // del frame end point is within our interval.
449 if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
451 // the del frame is within our interval... we need to split:
452 m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
454 // adjust start of current frame:
455 if (current_frame.m_lower_bound < del_frame.m_upper_bound)
457 current_frame.m_lower_bound= del_frame.m_upper_bound;
458 current_frame.m_changed= true;
463 // at this point the end of the del frame is >= current end
464 if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
466 // a part of the current interval needs to be preserved..
468 current_frame.m_upper_bound= del_frame.m_lower_bound;
469 current_frame.m_changed= true;
470 // and continue with the next interval:
474 // at this point; the whole frame needs to be deleted..
475 if ( it == m_intervals.begin())
477 m_intervals.erase(it);
478 it= m_intervals.begin();
482 IntervalList::iterator it2= it++;
483 m_intervals.erase(it2);
486 } // eo Intervals::sub(const Interval&)
490 * @brief returns if we contain an interval.
491 * @param other the interval to check.
492 * @return @a true if we cover the given interval, too.
494 bool Intervals::contains(const Interval& other) const
496 for(const_iterator it= begin();
500 if ( it->contains( other ))
506 } // eo Intervals::contains(const Interval&) const
510 * @brief returns if we contain an exact interval.
511 * @param other the interval to check.
512 * @return @a true if we axactly contains the given interval.
514 * @note thsi differs from contain in the way, that we return only @a true
515 * iff we have the given interval in our list; not only cover it.
517 bool Intervals::contains_exact(const Interval& other) const
519 for(const_iterator it= begin();
529 } // eo Intervals::contains_exact(const Interval&)const
533 * @brief returns if we contain another interval combination.
534 * @param other the intervals to check.
535 * @return @a true if we cover the given intervals, too.
537 * @internal we rely on the fact that the lists are sorted and contain
538 * disjoint intervals.
540 * So this method has a complexity of O(n).
542 bool Intervals::contains(const Intervals& other) const
544 const_iterator my_it= begin();
545 const_iterator other_it= other.begin();
546 while( my_it != end() and other_it!= other.end() )
548 // seek the first interval which contains the lower bound of the current other interval
549 while (my_it != end()
550 and my_it->m_lower_bound > other_it->m_lower_bound
551 and other_it->m_lower_bound >= my_it->m_upper_bound
560 if (not my_it->contains( *other_it ))
562 // if we don't contain the current other; we're done:
565 //else check the next other interval:
568 return (other_it == other.end());
569 } // eo Intervals::contains(const Intervals&) const
573 * @brief combines to interval combinates for equality
574 * @param other the other instance.
575 * @return @a true if the other is equal to the current.
577 * @internal since the lists are sorted, we compare the interval lists.
578 * Thus we have a complexity of O(n).
580 bool Intervals::operator==(const Intervals& other) const
582 // since we keep sorted lists: just compare the lists :-)
583 return m_intervals == other.m_intervals;
584 } // eo Intervals::operator==(const Intervals&)
587 Intervals& Intervals::operator+=(const Interval& other)
591 } // eo operator+=(const Interval&)
594 Intervals& Intervals::operator-=(const Interval& other)
598 } // eo operator-=(const Interval&)
602 * @brief adds the intervals of a second instance to us.
603 * @param other the other instance.
604 * @return self reference (allow chaining).
606 * @internal since we do simple loops over the other and our intervals
607 * we have a complexity of O(n^2).
609 * @todo optimize if complexity becomes a problem.
611 Intervals& Intervals::operator+=(const Intervals& other)
613 for(const_iterator it= other.begin();
620 } // eo operator+=(const Intervals&)
624 * @brief subtracts the intervals of a second instance from us.
625 * @param other the other instance.
626 * @return self reference (allow chaining).
628 * @internal since we do simple loops over the other and our intervals
629 * we have a complexity of O(n^2).
631 * @todo optimize if complexity becomes a problem.
633 Intervals& Intervals::operator-=(const Intervals& other)
641 for(const_iterator it= other.begin();
649 } // eo operator-=(const Intervals&)
659 * @brief fetches the value from the monotonic clock source.
660 * @param[out] seconds the seconds.
661 * @param[out] nano_seconds the nano seconds.
662 * @return @a true if the clock was successfully read.
664 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
666 struct timespec tp[1];
667 int res= ::syscall(__NR_clock_gettime, CLOCK_MONOTONIC, tp);
671 nano_seconds= tp->tv_nsec;
674 } // eo monotonic_clock_gettime(long int&,long int&)
678 * @brief fetches the value from the monotonic clock source.
679 * @return the time since system start in nanoseconds, 0 if read was unsuccessful
681 long long monotonic_clock_gettime_nano()
684 long int nano_seconds;
687 if (monotonic_clock_gettime(seconds,nano_seconds))
698 * @brief fetches the value from the monotonic clock source.
699 * @param[out] seconds the seconds.
700 * @param[out] nano_seconds the nano seconds.
701 * @return @a true if the clock was successfully read.
703 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
705 struct timespec tp[1];
706 int res= ::syscall(__NR_clock_gettime, CLOCK_REALTIME, tp);
710 nano_seconds= tp->tv_nsec;
713 } // eo realtime_clock_gettime(long int&,long int&)