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);
187 @brief returns the number of days till the next weekday which is set
188 @param start weekday to start checking
189 @note returns 0 if the start-day is set
191 int WEEK::days_till_set(WEEKDAY start)
196 for (unsigned int days=0; days < 8; days++)
198 unsigned int check=start+days;
201 if (is_set(static_cast<WEEKDAY>(check)))
205 throw logic_error("can't find next weekday");
212 @brief returns the number of days since the previous weekday which is set
213 @param start weekday to start checking
214 @note returns 0 if the start-day is set
216 int WEEK::days_since_set(WEEKDAY start)
221 for (unsigned int days=0; days < 8; days++)
223 int check=start-days;
226 if (is_set(static_cast<WEEKDAY>(check)))
230 throw logic_error("can't find next weekday");
236 std::string WEEK::get_daystring() const
239 for (int i = 0; i < 7; i++)
246 std::string WEEK::get_displaystring() const
250 // From Monday to Saturday
252 for (int i = 1; i < 7; i++)
256 if (!weekdays_str.empty())
257 weekdays_str += ", ";
259 weekdays_str += get_day_display(static_cast<WEEKDAY>(i));
261 // check if we can group two or more days
263 while (days[j] && j < 7)
267 // Sunday end of week? j -> 7
268 if (j-i > 0 && j == 6 && days[0])
274 weekdays_str += "-" + get_day_display(SU);
276 weekdays_str += "-" + get_day_display(static_cast<WEEKDAY>(j));
284 if (days[0] && j != 7)
286 if (!weekdays_str.empty())
287 weekdays_str += ", ";
289 weekdays_str += get_day_display(SU);
295 std::string WEEK::get_netfilterstring() const
298 for (int i = 0; i < 7; i++)
303 out+=get_english_display(static_cast<WEEKDAY>(i));;
309 std::string WEEK::get_day_display(WEEKDAY day)
315 weekday_str = i18n("Mon");
318 weekday_str = i18n("Tue");
321 weekday_str = i18n("Wed");
324 weekday_str = i18n("Thu");
327 weekday_str = i18n("Fri");
330 weekday_str = i18n("Sat");
333 weekday_str = i18n("Sun");
342 std::string WEEK::get_english_display(WEEKDAY day)
375 string get_month_name(unsigned char month)
380 rtn = i18n("January");
383 rtn = i18n("February");
401 rtn = i18n("August");
404 rtn = i18n("September");
407 rtn = i18n("October");
410 rtn = i18n("November");
413 rtn = i18n("December");
418 out << i18n("Illegal month:") << " " << month;
428 ** implementaion of Interval
433 * @brief clears the interval (make it empty).
435 void Interval::clear()
437 m_lower_bound = m_upper_bound = 0;
438 } // eo Interval::clear()
442 * @brief tests if there is some overlapping with another interval
443 * @param other the other interval
444 * @return @a true if the two intervals have a non empty intersection.
446 bool Interval::intersects(const Interval& other) const
449 // // other start within this:
450 (other.m_lower_bound >= m_lower_bound and other.m_lower_bound < m_upper_bound )
451 // // other end within this:
452 or (other.m_upper_bound > m_lower_bound and other.m_upper_bound <= m_upper_bound )
453 // // other contains this
454 or (other.m_lower_bound <= m_lower_bound and other.m_upper_bound >= m_upper_bound )
456 } // eo Interval::intersects(const Interval&)
460 * @brief tests if the current interval (fully) contains another one.
461 * @param other the other interval.
462 * @return @a true if the current interval fully contains the other interval.
464 bool Interval::contains(const Interval& other) const
466 return (other.m_lower_bound >= m_lower_bound)
467 and (other.m_upper_bound <= m_upper_bound)
469 } // eo Interval::contains(const Interval& other) const
473 ** implementation of Intervals:
477 Intervals::Intervals()
479 } // eo Intervals::Intervals
482 void Intervals::clear()
485 } // eo Intervals::clear()
488 * @brief tests if one of the intervals of the list intersects with the given interval.
489 * @param other the interval to check for intersection.
490 * @return @a true if there is an intersection.
492 bool Intervals::intersects(const Interval& other) const
494 for(const_iterator it= begin();
498 if ( it->intersects(other) )
504 } // eo Intervals::intersects(const Interval&) const
508 * @brief tests if we have at least one intersection with another Intervals instance.
509 * @param other the other instance.
510 * @return @a true if there is an intersection.
512 bool Intervals::intersects(const Intervals& other) const
514 for(const_iterator it= begin();
518 if ( other.intersects( *it ) )
524 } // eo Intervals::intersects(const Intervals&) const
528 * @brief adds a new interval to the list.
529 * @param new_frame the new interval.
531 * Adds the interval to the list and joins overlapping intervals.
533 * @internal complexity O(n).
535 void Intervals::add(const Interval& new_frame)
537 if (not new_frame.is_valid() or new_frame.empty())
539 // well... we will not insert invalid or empty frames!
542 for (IntervalList::iterator it= m_intervals.begin();
543 it != m_intervals.end();
546 Interval& current_frame = *it;
547 if ( new_frame.m_lower_bound > current_frame.m_upper_bound )
549 // new_frame begins later than current end; go on:
552 // at this point: the begin of the new frame is less then the current end.
553 // now let's determine how we can insert the new frame:
555 if ( new_frame.m_upper_bound < current_frame.m_lower_bound )
557 // new disjoint frame; insert it before the current frame:
558 m_intervals.insert( it, new_frame );
562 // at this point: the end of the new frame is >= current begin.
563 if ( new_frame.m_upper_bound <= current_frame.m_upper_bound )
565 // the end of the new frame is within our current frame; we need to combine
566 if (new_frame.m_lower_bound < current_frame.m_lower_bound)
568 // the new interval starts earlier; we need to adjust our current frame:
569 current_frame.m_lower_bound = new_frame.m_lower_bound;
570 current_frame.m_changed = true;
572 // NOTE no "else" part needed since in that case our current frame already
573 // contains the new one!
578 // at this point: end of new frame > end of current frame
579 // so we need to extend the current frame; at least the end.
580 // But we need to deal with intersects of following frames... *sigh*
582 // first the simple part: let's see if we need to move the start:
583 if ( new_frame.m_lower_bound < current_frame.m_lower_bound)
585 // yes, we need to move the start:
586 current_frame.m_lower_bound = new_frame.m_lower_bound;
587 current_frame.m_changed= true;
590 // now let's extend the end:
591 current_frame.m_upper_bound = new_frame.m_upper_bound;
592 current_frame.m_changed = true;
594 // well... let's walk through the following frames; looking for more joins...:
595 IntervalList::iterator it2 = it;
596 while( ++(it2=it) != m_intervals.end()
597 and current_frame.m_upper_bound >= it2->m_lower_bound
600 Interval next_frame= *it2;
601 if ( current_frame.m_upper_bound < next_frame.m_upper_bound )
603 // in this case our end is within the next frame.
605 current_frame.m_upper_bound = next_frame.m_upper_bound;
607 // and remove the next frame since the current frame contains it (now):
608 m_intervals.erase(it2);
613 // at this point: new frame starts later than the last frame ends
614 // append the new frame:
615 m_intervals.push_back( new_frame );
616 } // eo Intervals::add(const Interval&)
620 * @brief subtracts a time interval from the list.
621 * @param del_frame the time interval to subtract.
623 * removes the time interval from the list; cut off parts from or remove existing
624 * intervals if they overlap.
626 * @internal complexity O(n).
628 void Intervals::sub(const Interval& del_frame)
630 if (not del_frame.is_valid() or del_frame.empty() )
634 for (IntervalList::iterator it= m_intervals.begin();
635 it != m_intervals.end();
638 Interval& current_frame = *it;
639 if ( del_frame.m_lower_bound >= current_frame.m_upper_bound )
641 // del_frame begins later than current end; go on:
645 // at this point: the begin of the del frame is less then the current end.
646 if ( del_frame.m_upper_bound < current_frame.m_lower_bound )
648 // end is before our start; nothing to do.
651 // at this point: the end of the del frame is >= current begin.
652 if ( del_frame.m_upper_bound < current_frame.m_upper_bound )
654 // del frame end point is within our interval.
655 if ( del_frame.m_lower_bound > current_frame.m_lower_bound)
657 // the del frame is within our interval... we need to split:
658 m_intervals.insert(it, Interval( current_frame.m_lower_bound, del_frame.m_lower_bound ) );
660 // adjust start of current frame:
661 if (current_frame.m_lower_bound < del_frame.m_upper_bound)
663 current_frame.m_lower_bound= del_frame.m_upper_bound;
664 current_frame.m_changed= true;
669 // at this point the end of the del frame is >= current end
670 if ( del_frame.m_lower_bound > current_frame.m_lower_bound )
672 // a part of the current interval needs to be preserved..
674 current_frame.m_upper_bound= del_frame.m_lower_bound;
675 current_frame.m_changed= true;
676 // and continue with the next interval:
680 // at this point; the whole frame needs to be deleted..
681 if ( it == m_intervals.begin())
683 m_intervals.erase(it);
684 it= m_intervals.begin();
688 IntervalList::iterator it2= it++;
689 m_intervals.erase(it2);
692 } // eo Intervals::sub(const Interval&)
696 * @brief returns if we contain an interval.
697 * @param other the interval to check.
698 * @return @a true if we cover the given interval, too.
700 bool Intervals::contains(const Interval& other) const
702 for(const_iterator it= begin();
706 if ( it->contains( other ))
712 } // eo Intervals::contains(const Interval&) const
716 * @brief returns if we contain an exact interval.
717 * @param other the interval to check.
718 * @return @a true if we axactly contains the given interval.
720 * @note thsi differs from contain in the way, that we return only @a true
721 * iff we have the given interval in our list; not only cover it.
723 bool Intervals::contains_exact(const Interval& other) const
725 for(const_iterator it= begin();
735 } // eo Intervals::contains_exact(const Interval&)const
739 * @brief returns if we contain another interval combination.
740 * @param other the intervals to check.
741 * @return @a true if we cover the given intervals, too.
743 * @internal we rely on the fact that the lists are sorted and contain
744 * disjoint intervals.
746 * So this method has a complexity of O(n).
748 bool Intervals::contains(const Intervals& other) const
750 const_iterator my_it= begin();
751 const_iterator other_it= other.begin();
752 while( my_it != end() and other_it!= other.end() )
754 // seek the first interval which contains the lower bound of the current other interval
755 while (my_it != end()
756 and my_it->m_lower_bound > other_it->m_lower_bound
757 and other_it->m_lower_bound >= my_it->m_upper_bound
766 if (not my_it->contains( *other_it ))
768 // if we don't contain the current other; we're done:
771 //else check the next other interval:
774 return (other_it == other.end());
775 } // eo Intervals::contains(const Intervals&) const
779 * @brief combines to interval combinates for equality
780 * @param other the other instance.
781 * @return @a true if the other is equal to the current.
783 * @internal since the lists are sorted, we compare the interval lists.
784 * Thus we have a complexity of O(n).
786 bool Intervals::operator==(const Intervals& other) const
788 // since we keep sorted lists: just compare the lists :-)
789 return m_intervals == other.m_intervals;
790 } // eo Intervals::operator==(const Intervals&)
793 Intervals& Intervals::operator+=(const Interval& other)
797 } // eo operator+=(const Interval&)
800 Intervals& Intervals::operator-=(const Interval& other)
804 } // eo operator-=(const Interval&)
808 * @brief adds the intervals of a second instance to us.
809 * @param other the other instance.
810 * @return self reference (allow chaining).
812 * @internal since we do simple loops over the other and our intervals
813 * we have a complexity of O(n^2).
815 * @todo optimize if complexity becomes a problem.
817 Intervals& Intervals::operator+=(const Intervals& other)
819 for(const_iterator it= other.begin();
826 } // eo operator+=(const Intervals&)
830 * @brief subtracts the intervals of a second instance from us.
831 * @param other the other instance.
832 * @return self reference (allow chaining).
834 * @internal since we do simple loops over the other and our intervals
835 * we have a complexity of O(n^2).
837 * @todo optimize if complexity becomes a problem.
839 Intervals& Intervals::operator-=(const Intervals& other)
847 for(const_iterator it= other.begin();
855 } // eo operator-=(const Intervals&)
865 * @brief fetches the value from the monotonic clock source.
866 * @param[out] seconds the seconds.
867 * @param[out] nano_seconds the nano seconds.
868 * @return @a true if the clock was successfully read.
870 bool monotonic_clock_gettime(long int& seconds, long int& nano_seconds)
872 struct timespec tp[1];
873 int res= ::syscall(__NR_clock_gettime, CLOCK_MONOTONIC, tp);
877 nano_seconds= tp->tv_nsec;
880 } // eo monotonic_clock_gettime(long int&,long int&)
884 * @brief fetches the value from the monotonic clock source.
885 * @return the time since system start in nanoseconds, 0 if read was unsuccessful
887 long long monotonic_clock_gettime_nano()
890 long int nano_seconds;
893 if (monotonic_clock_gettime(seconds,nano_seconds))
904 * @brief fetches the value from the monotonic clock source.
905 * @param[out] seconds the seconds.
906 * @param[out] nano_seconds the nano seconds.
907 * @return @a true if the clock was successfully read.
909 bool realtime_clock_gettime(long int& seconds, long int& nano_seconds)
911 struct timespec tp[1];
912 int res= ::syscall(__NR_clock_gettime, CLOCK_REALTIME, tp);
916 nano_seconds= tp->tv_nsec;
919 } // eo realtime_clock_gettime(long int&,long int&)