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 void WEEK::set(const std::string& daystring)
171 int len=daystring.length();
172 for (int p=0; p < len; p++)
179 if (!(c >> wnr) || wnr<0 || wnr >6)
180 throw range_error("illegal weekday >"+string(nr)+"< in "+daystring);
186 std::string WEEK::get_daystring() const
189 for (int i = 0; i < 7; i++)
196 std::string WEEK::get_displaystring() const
200 // From Monday to Saturday
202 for (int i = 1; i < 7; i++)
206 if (!weekdays_str.empty())
207 weekdays_str += ", ";
209 weekdays_str += get_day_display(static_cast<WEEKDAY>(i));
211 // check if we can group two or more days
213 while (days[j] && j < 7)
217 // Sunday end of week? j -> 7
218 if (j-i > 0 && j == 6 && days[0])
224 weekdays_str += "-" + get_day_display(SU);
226 weekdays_str += "-" + get_day_display(static_cast<WEEKDAY>(j));
234 if (days[0] && j != 7)
236 if (!weekdays_str.empty())
237 weekdays_str += ", ";
239 weekdays_str += get_day_display(SU);
245 std::string WEEK::get_netfilterstring() const
248 for (int i = 0; i < 7; i++)
253 out+=get_english_display(static_cast<WEEKDAY>(i));;
259 std::string WEEK::get_day_display(WEEKDAY day)
265 weekday_str = i18n("Mon");
268 weekday_str = i18n("Tue");
271 weekday_str = i18n("Wed");
274 weekday_str = i18n("Thu");
277 weekday_str = i18n("Fri");
280 weekday_str = i18n("Sat");
283 weekday_str = i18n("Sun");
292 std::string WEEK::get_english_display(WEEKDAY day)
325 string get_month_name(unsigned char month)
330 rtn = i18n("January");
333 rtn = i18n("February");
351 rtn = i18n("August");
354 rtn = i18n("September");
357 rtn = i18n("October");
360 rtn = i18n("November");
363 rtn = i18n("December");
368 out << i18n("Illegal month:") << " " << month;
378 ** implementaion of Interval
383 * @brief clears the interval (make it empty).
385 void Interval::clear()
387 m_lower_bound = m_upper_bound = 0;
388 } // eo Interval::clear()
392 * @brief tests if there is some overlapping with another interval
393 * @param other the other interval
394 * @return @a true if the two intervals have a non empty intersection.
396 bool Interval::intersects(const Interval& other) const
399 // // other start within this:
400 (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
401 // // other end within this:
402 or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
403 // // other contains this
404 or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
406 } // eo Interval::intersects(const Interval&)
410 * @brief tests if the current interval (fully) contains another one.
411 * @param other the other interval.
412 * @return @a true if the current interval fully contains the other interval.
414 bool Interval::contains(const Interval& other) const
416 return (other.m_lower_bound >= m_lower_bound)
417 and (other.m_upper_bound <= m_upper_bound)
419 } // eo Interval::contains(const Interval& other) const
423 ** implementation of Intervals:
427 Intervals::Intervals()
429 } // eo Intervals::Intervals
432 void Intervals::clear()
435 } // eo Intervals::clear()
438 * @brief tests if one of the intervals of the list intersects with the given interval.
439 * @param other the interval to check for intersection.
440 * @return @a true if there is an intersection.
442 bool Intervals::intersects(const Interval& other) const
444 for(const_iterator it= begin();
448 if ( it->intersects(other) )
454 } // eo Intervals::intersects(const Interval&) const
458 * @brief tests if we have at least one intersection with another Intervals instance.
459 * @param other the other instance.
460 * @return @a true if there is an intersection.
462 bool Intervals::intersects(const Intervals& other) const
464 for(const_iterator it= begin();
468 if ( other.intersects( *it ) )
474 } // eo Intervals::intersects(const Intervals&) const
478 * @brief adds a new interval to the list.
479 * @param new_frame the new interval.
481 * Adds the interval to the list and joins overlapping intervals.
483 * @internal complexity O(n).
485 void Intervals::add(const Interval& new_frame)
487 if (not new_frame.is_valid() or new_frame.empty())
489 // well... we will not insert invalid or empty frames!
492 for (IntervalList::iterator it= m_intervals.begin();
493 it != m_intervals.end();
496 Interval& current_frame = *it;
497 if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
499 // new_frame begins later than current end; go on:
502 // at this point: the begin of the new frame is less then the current end.
503 // now let's determine how we can insert the new frame:
505 if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
507 // new disjoint frame; insert it before the current frame:
508 m_intervals.insert( it, new_frame );
512 // at this point: the end of the new frame is >= current begin.
513 if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
515 // the end of the new frame is within our current frame; we need to combine
516 if (new_frame.m_lower_bound < current_frame.m_lower_bound)
518 // the new interval starts earlier; we need to adjust our current frame:
519 current_frame.m_lower_bound = new_frame.m_lower_bound;
520 current_frame.m_changed = true;
522 // NOTE no "else" part needed since in that case our current frame already
523 // contains the new one!
528 // at this point: end of new frame > end of current frame
529 // so we need to extend the current frame; at least the end.
530 // But we need to deal with intersects of following frames... *sigh*
532 // first the simple part: let's see if we need to move the start:
533 if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
535 // yes, we need to move the start:
536 current_frame.m_lower_bound = new_frame.m_lower_bound;
537 current_frame.m_changed= true;
540 // now let's extend the end:
541 current_frame.m_upper_bound = new_frame.m_upper_bound;
542 current_frame.m_changed = true;
544 // well... let's walk through the following frames; looking for more joins...:
545 IntervalList::iterator it2 = it;
546 while( ++(it2=it) != m_intervals.end()
547 and current_frame.m_upper_bound >= it2->m_lower_bound
550 Interval next_frame= *it2;
551 if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
553 // in this case our end is within the next frame.
555 current_frame.m_upper_bound = next_frame.m_upper_bound;
557 // and remove the next frame since the current frame contains it (now):
558 m_intervals.erase(it2);
563 // at this point: new frame starts later than the last frame ends
564 // append the new frame:
565 m_intervals.push_back( new_frame );
566 } // eo Intervals::add(const Interval&)
570 * @brief subtracts a time interval from the list.
571 * @param del_frame the time interval to subtract.
573 * removes the time interval from the list; cut off parts from or remove existing
574 * intervals if they overlap.
576 * @internal complexity O(n).
578 void Intervals::sub(const Interval& del_frame)
580 if (not del_frame.is_valid() or del_frame.empty() )
584 for (IntervalList::iterator it= m_intervals.begin();
585 it != m_intervals.end();
588 Interval& current_frame = *it;
589 if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
591 // del_frame begins later than current end; go on:
595 // at this point: the begin of the del frame is less then the current end.
596 if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
598 // end is before our start; nothing to do.
601 // at this point: the end of the del frame is >= current begin.
602 if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
604 // del frame end point is within our interval.
605 if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
607 // the del frame is within our interval... we need to split:
608 m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
610 // adjust start of current frame:
611 if (current_frame.m_lower_bound < del_frame.m_upper_bound)
613 current_frame.m_lower_bound= del_frame.m_upper_bound;
614 current_frame.m_changed= true;
619 // at this point the end of the del frame is >= current end
620 if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
622 // a part of the current interval needs to be preserved..
624 current_frame.m_upper_bound= del_frame.m_lower_bound;
625 current_frame.m_changed= true;
626 // and continue with the next interval:
630 // at this point; the whole frame needs to be deleted..
631 if ( it == m_intervals.begin())
633 m_intervals.erase(it);
634 it= m_intervals.begin();
638 IntervalList::iterator it2= it++;
639 m_intervals.erase(it2);
642 } // eo Intervals::sub(const Interval&)
646 * @brief returns if we contain an interval.
647 * @param other the interval to check.
648 * @return @a true if we cover the given interval, too.
650 bool Intervals::contains(const Interval& other) const
652 for(const_iterator it= begin();
656 if ( it->contains( other ))
662 } // eo Intervals::contains(const Interval&) const
666 * @brief returns if we contain an exact interval.
667 * @param other the interval to check.
668 * @return @a true if we axactly contains the given interval.
670 * @note thsi differs from contain in the way, that we return only @a true
671 * iff we have the given interval in our list; not only cover it.
673 bool Intervals::contains_exact(const Interval& other) const
675 for(const_iterator it= begin();
685 } // eo Intervals::contains_exact(const Interval&)const
689 * @brief returns if we contain another interval combination.
690 * @param other the intervals to check.
691 * @return @a true if we cover the given intervals, too.
693 * @internal we rely on the fact that the lists are sorted and contain
694 * disjoint intervals.
696 * So this method has a complexity of O(n).
698 bool Intervals::contains(const Intervals& other) const
700 const_iterator my_it= begin();
701 const_iterator other_it= other.begin();
702 while( my_it != end() and other_it!= other.end() )
704 // seek the first interval which contains the lower bound of the current other interval
705 while (my_it != end()
706 and my_it->m_lower_bound > other_it->m_lower_bound
707 and other_it->m_lower_bound >= my_it->m_upper_bound
716 if (not my_it->contains( *other_it ))
718 // if we don't contain the current other; we're done:
721 //else check the next other interval:
724 return (other_it == other.end());
725 } // eo Intervals::contains(const Intervals&) const
729 * @brief combines to interval combinates for equality
730 * @param other the other instance.
731 * @return @a true if the other is equal to the current.
733 * @internal since the lists are sorted, we compare the interval lists.
734 * Thus we have a complexity of O(n).
736 bool Intervals::operator==(const Intervals& other) const
738 // since we keep sorted lists: just compare the lists :-)
739 return m_intervals == other.m_intervals;
740 } // eo Intervals::operator==(const Intervals&)
743 Intervals& Intervals::operator+=(const Interval& other)
747 } // eo operator+=(const Interval&)
750 Intervals& Intervals::operator-=(const Interval& other)
754 } // eo operator-=(const Interval&)
758 * @brief adds the intervals of a second instance to us.
759 * @param other the other instance.
760 * @return self reference (allow chaining).
762 * @internal since we do simple loops over the other and our intervals
763 * we have a complexity of O(n^2).
765 * @todo optimize if complexity becomes a problem.
767 Intervals& Intervals::operator+=(const Intervals& other)
769 for(const_iterator it= other.begin();
776 } // eo operator+=(const Intervals&)
780 * @brief subtracts the intervals of a second instance from us.
781 * @param other the other instance.
782 * @return self reference (allow chaining).
784 * @internal since we do simple loops over the other and our intervals
785 * we have a complexity of O(n^2).
787 * @todo optimize if complexity becomes a problem.
789 Intervals& Intervals::operator-=(const Intervals& other)
797 for(const_iterator it= other.begin();
805 } // eo operator-=(const Intervals&)
815 * @brief fetches the value from the monotonic clock source.
816 * @param[out] seconds the seconds.
817 * @param[out] nano_seconds the nano seconds.
818 * @return @a true if the clock was successfully read.
820 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
822 struct timespec tp[1];
823 int res= ::syscall(__NR_clock_gettime, CLOCK_MONOTONIC, tp);
827 nano_seconds= tp->tv_nsec;
830 } // eo monotonic_clock_gettime(long int&,long int&)
834 * @brief fetches the value from the monotonic clock source.
835 * @return the time since system start in nanoseconds, 0 if read was unsuccessful
837 long long monotonic_clock_gettime_nano()
840 long int nano_seconds;
843 if (monotonic_clock_gettime(seconds,nano_seconds))
854 * @brief fetches the value from the monotonic clock source.
855 * @param[out] seconds the seconds.
856 * @param[out] nano_seconds the nano seconds.
857 * @return @a true if the clock was successfully read.
859 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
861 struct timespec tp[1];
862 int res= ::syscall(__NR_clock_gettime, CLOCK_REALTIME, tp);
866 nano_seconds= tp->tv_nsec;
869 } // eo realtime_clock_gettime(long int&,long int&)