23#include "recurrencerule.h" 
   27#include <tqdatetime.h> 
   28#include <tqstringlist.h> 
   36const int LOOP_LIMIT = 10000;
 
   60long long ownSecsTo( 
const TQDateTime &dt1, 
const TQDateTime &dt2 )
 
   62  long long res = 
static_cast<long long>( dt1.date().daysTo( dt2.date() ) ) * 24*3600;
 
   63  res += dt1.time().secsTo( dt2.time() );
 
   77    static TQString dayName( 
short day );
 
   79    static TQDate getNthWeek( 
int year, 
int weeknumber, 
short weekstart = 1 );
 
   80    static int weekNumbersInYear( 
int year, 
short weekstart = 1 );
 
   81    static int getWeekNumber( 
const TQDate &date, 
short weekstart, 
int *year = 0 );
 
   82    static int getWeekNumberNeg( 
const TQDate &date, 
short weekstart, 
int *year = 0 );
 
   87TQString DateHelper::dayName( 
short day )
 
   90    case 1: 
return "MO"; 
break;
 
   91    case 2: 
return "TU"; 
break;
 
   92    case 3: 
return "WE"; 
break;
 
   93    case 4: 
return "TH"; 
break;
 
   94    case 5: 
return "FR"; 
break;
 
   95    case 6: 
return "SA"; 
break;
 
   96    case 7: 
return "SU"; 
break;
 
  103TQDate DateHelper::getNthWeek( 
int year, 
int weeknumber, 
short weekstart )
 
  105  if ( weeknumber == 0 ) 
return TQDate();
 
  107  TQDate dt( year, 1, 4 ); 
 
  108  int adjust = -(7 + dt.dayOfWeek() - weekstart) % 7;
 
  109  if ( weeknumber > 0 ) {
 
  110    dt = dt.addDays( 7 * (weeknumber-1) + adjust );
 
  111  } 
else if ( weeknumber < 0 ) {
 
  112    dt = dt.addYears( 1 );
 
  113    dt = dt.addDays( 7 * weeknumber + adjust );
 
  119int DateHelper::getWeekNumber( 
const TQDate &date, 
short weekstart, 
int *year )
 
  122  if ( year ) *year = date.year();
 
  123  TQDate dt( date.year(), 1, 4 ); 
 
  124  dt = dt.addDays( -(7 + dt.dayOfWeek() - weekstart) % 7 ); 
 
  125  TQDate dtn( date.year()+1, 1, 4 ); 
 
  126  dtn = dtn.addDays( -(7 + dtn.dayOfWeek() - weekstart) % 7 );
 
  128  int daysto = dt.daysTo( date );
 
  129  int dayston = dtn.daysTo( date );
 
  131    if ( year ) *year = date.year()-1;
 
  132    dt = TQDate( date.year()-1, 1, 4 );
 
  133    dt = dt.addDays( -(7 + dt.dayOfWeek() - weekstart) % 7 ); 
 
  134    daysto = dt.daysTo( date );
 
  135  } 
else if ( dayston >= 0 ) {
 
  137    if ( year ) *year = date.year() + 1;
 
  141  return daysto / 7 + 1;
 
  144int DateHelper::weekNumbersInYear( 
int year, 
short weekstart )
 
  146  TQDate dt( year, 1, weekstart );
 
  147  TQDate dt1( year + 1, 1, weekstart );
 
  148  return dt.daysTo( dt1 ) / 7;
 
  152int DateHelper::getWeekNumberNeg( 
const TQDate &date, 
short weekstart, 
int *year )
 
  154  int weekpos = getWeekNumber( date, weekstart, year );
 
  155  return weekNumbersInYear( *year, weekstart ) - weekpos - 1;
 
  167RecurrenceRule::Constraint::Constraint( 
int wkst )
 
  173RecurrenceRule::Constraint::Constraint( 
const TQDateTime &preDate, PeriodType type, 
int wkst )
 
  176  readDateTime( preDate, type );
 
  179void RecurrenceRule::Constraint::clear()
 
  198  if ( weeknumber == 0 ) {
 
  199    if ( year > 0 && year != dt.year() ) 
return false;
 
  202    if ( weeknumber > 0 &&
 
  203         weeknumber != DateHelper::getWeekNumber( dt, weekstart, &y ) ) 
return false;
 
  204    if ( weeknumber < 0 &&
 
  205         weeknumber != DateHelper::getWeekNumberNeg( dt, weekstart, &y ) ) 
return false;
 
  206    if ( year > 0 && year != y ) 
return false;
 
  209  if ( month > 0 && month != dt.month() ) 
return false;
 
  210  if ( day > 0 && day != dt.day() ) 
return false;
 
  211  if ( day < 0 && dt.day() != (dt.daysInMonth() + day + 1 ) ) 
return false;
 
  213    if ( weekday != dt.dayOfWeek() ) 
return false;
 
  214    if ( weekdaynr != 0 ) {
 
  217      bool inMonth = (type == rMonthly) || ( type == rYearly && month > 0 );
 
  219      if ( weekdaynr > 0 && inMonth &&
 
  220           weekdaynr != (dt.day() - 1)/7 + 1 ) 
return false;
 
  221      if ( weekdaynr < 0 && inMonth &&
 
  222           weekdaynr != -((dt.daysInMonth() - dt.day() )/7 + 1 ) )
 
  225      if ( weekdaynr > 0 && !inMonth &&
 
  226           weekdaynr != (dt.dayOfYear() - 1)/7 + 1 ) 
return false;
 
  227      if ( weekdaynr < 0 && !inMonth &&
 
  228           weekdaynr != -((dt.daysInYear() - dt.dayOfYear() )/7 + 1 ) )
 
  232  if ( yearday > 0 && yearday != dt.dayOfYear() ) 
return false;
 
  233  if ( yearday < 0 && yearday != dt.daysInYear() - dt.dayOfYear() + 1 )
 
  240  if ( !matches( dt.date(), type ) ) 
return false;
 
  241  if ( hour >= 0 && hour != dt.time().hour() ) 
return false;
 
  242  if ( minute >= 0 && minute != dt.time().minute() ) 
return false;
 
  243  if ( second >= 0 && second != dt.time().second() ) 
return false;
 
  247bool RecurrenceRule::Constraint::isConsistent( PeriodType )
 const 
  256  dt.setTime( TQTime( 0, 0, 0 ) );
 
  257  dt.setDate( TQDate( year, (month>0)?month:1, (day>0)?day:1 ) );
 
  259    dt = dt.addDays( dt.date().daysInMonth() + day );
 
  262      dt.setTime( TQTime( hour, minute, second ) ); 
break;
 
  264      dt.setTime( TQTime( hour, minute, 1 ) ); 
break;
 
  266      dt.setTime( TQTime( hour, 1, 1 ) ); 
break;
 
  270      dt = DateHelper::getNthWeek( year, weeknumber, weekstart ); 
break;
 
  272      dt.setDate( TQDate( year, month, 1 ) ); 
break;
 
  274      dt.setDate( TQDate( year, 1, 1 ) ); 
break;
 
  305  TQTime tm( hour, minute, second );
 
  306  if ( !isConsistent( type ) ) 
return result;
 
  308  if ( !done && day > 0 && month > 0 ) {
 
  309    TQDateTime dt( TQDate( year, month, day ), tm );
 
  310    if ( dt.isValid() ) result.append( dt );
 
  313  if ( !done && day < 0 && month > 0 ) {
 
  314    TQDateTime dt( TQDate( year, month, 1 ), tm );
 
  315    dt = dt.addDays( dt.date().daysInMonth() + day );
 
  316    if ( dt.isValid() ) result.append( dt );
 
  321  if ( !done && weekday == 0 && weeknumber == 0 && yearday == 0 ) {
 
  323    uint mstart = (month>0) ? month : 1;
 
  324    uint mend = (month <= 0) ? 12 : month;
 
  325    for ( uint m = mstart; m <= mend; ++m ) {
 
  329      } 
else if ( day < 0 ) {
 
  330        TQDate date( year, month, 1 );
 
  331        dstart = dend = date.daysInMonth() + day + 1;
 
  333        TQDate date( year, month, 1 );
 
  335        dend = date.daysInMonth();
 
  337      for ( uint d = dstart; d <= dend; ++d ) {
 
  338        TQDateTime dt( TQDate( year, m, d ), tm );
 
  339        if ( dt.isValid() ) result.append( dt );
 
  347  if ( !done && yearday != 0 ) {
 
  349    TQDate d( year + ((yearday>0)?0:1), 1, 1 );
 
  350    d = d.addDays( yearday - ((yearday>0)?1:0) );
 
  351    result.append( TQDateTime( d, tm ) );
 
  356  if ( !done && weeknumber != 0 ) {
 
  357    TQDate wst( DateHelper::getNthWeek( year, weeknumber, weekstart ) );
 
  358    if ( weekday != 0 ) {
 
  359      wst = wst.addDays( (7 + weekday - weekstart ) % 7 );
 
  360      result.append( TQDateTime( wst, tm ) );
 
  362      for ( 
int i = 0; i < 7; ++i ) {
 
  363        result.append( TQDateTime( wst, tm ) );
 
  364        wst = wst.addDays( 1 );
 
  371  if ( !done && weekday != 0 ) {
 
  372    TQDate dt( year, 1, 1 );
 
  376    bool inMonth = ( type == rMonthly) || ( type == rYearly && month > 0 );
 
  377    if ( inMonth && month > 0 ) {
 
  378      dt = TQDate( year, month, 1 );
 
  381    if ( weekdaynr < 0 ) {
 
  384        dt = dt.addMonths( 1 );
 
  386        dt = dt.addYears( 1 );
 
  388    int adj = ( 7 + weekday - dt.dayOfWeek() ) % 7;
 
  389    dt = dt.addDays( adj ); 
 
  391    if ( weekdaynr > 0 ) {
 
  392      dt = dt.addDays( ( weekdaynr - 1 ) * 7 );
 
  393      result.append( TQDateTime( dt, tm ) );
 
  394    } 
else if ( weekdaynr < 0 ) {
 
  395      dt = dt.addDays( weekdaynr * 7 );
 
  396      result.append( TQDateTime( dt, tm ) );
 
  399      for ( 
int i = 0; i < maxloop; ++i ) {
 
  400        result.append( TQDateTime( dt, tm ) );
 
  401        dt = dt.addDays( 7 );
 
  409  DateTimeList::Iterator it;
 
  410  for ( it = result.begin(); it != result.end(); ++it ) {
 
  411    if ( matches( *it, type ) ) valid.append( *it );
 
  423  TQDateTime dt( intervalDateTime( type ) );
 
  428      dt = dt.addSecs( freq ); 
break;
 
  430      dt = dt.addSecs( 60*freq ); 
break;
 
  432      dt = dt.addSecs( 3600 * freq ); 
break;
 
  434      dt = dt.addDays( freq ); 
break;
 
  436      dt = dt.addDays( 7*freq ); 
break;
 
  438      dt = dt.addMonths( freq ); 
break;
 
  440      dt = dt.addYears( freq ); 
break;
 
  445  readDateTime( dt, type );
 
  450bool RecurrenceRule::Constraint::readDateTime( 
const TQDateTime &preDate, PeriodType type )
 
  456      second = preDate.time().second();
 
  458      minute = preDate.time().minute();
 
  460      hour = preDate.time().hour();
 
  462      day = preDate.date().day();
 
  464      month = preDate.date().month();
 
  466      year = preDate.date().year();
 
  471      weeknumber = DateHelper::getWeekNumber( preDate.date(), weekstart, &year );
 
  480RecurrenceRule::RecurrenceRule( )
 
  481: mPeriod( rNone ), mFrequency( 0 ), mIsReadOnly( false ),
 
  491  mDateStart = r.mDateStart;
 
  492  mDuration = r.mDuration;
 
  493  mDateEnd = r.mDateEnd;
 
  494  mFrequency = r.mFrequency;
 
  496  mIsReadOnly = r.mIsReadOnly;
 
  497  mFloating = r.mFloating;
 
  499  mBySeconds = r.mBySeconds;
 
  500  mByMinutes = r.mByMinutes;
 
  501  mByHours = r.mByHours;
 
  503  mByMonthDays = r.mByMonthDays;
 
  504  mByYearDays = r.mByYearDays;
 
  505  mByWeekNumbers = r.mByWeekNumbers;
 
  506  mByMonths = r.mByMonths;
 
  507  mBySetPos = r.mBySetPos;
 
  508  mWeekStart = r.mWeekStart;
 
  513RecurrenceRule::~RecurrenceRule()
 
  519  if ( mPeriod != r.mPeriod ) 
return false;
 
  520  if ( mDateStart != r.mDateStart ) 
return false;
 
  521  if ( mDuration != r.mDuration ) 
return false;
 
  522  if ( mDateEnd != r.mDateEnd ) 
return false;
 
  523  if ( mFrequency != r.mFrequency ) 
return false;
 
  525  if ( mIsReadOnly != r.mIsReadOnly ) 
return false;
 
  526  if ( mFloating != r.mFloating ) 
return false;
 
  528  if ( mBySeconds != r.mBySeconds ) 
return false;
 
  529  if ( mByMinutes != r.mByMinutes ) 
return false;
 
  530  if ( mByHours != r.mByHours ) 
return false;
 
  531  if ( mByDays != r.mByDays ) 
return false;
 
  532  if ( mByMonthDays != r.mByMonthDays ) 
return false;
 
  533  if ( mByYearDays != r.mByYearDays ) 
return false;
 
  534  if ( mByWeekNumbers != r.mByWeekNumbers ) 
return false;
 
  535  if ( mByMonths != r.mByMonths ) 
return false;
 
  536  if ( mBySetPos != r.mBySetPos ) 
return false;
 
  537  if ( mWeekStart != r.mWeekStart ) 
return false;
 
  544  if ( !mObservers.contains( observer ) )
 
  545    mObservers.append( observer );
 
  550  if ( mObservers.contains( observer ) )
 
  551    mObservers.remove( observer );
 
  556void RecurrenceRule::setRecurrenceType( PeriodType period )
 
  565  if ( result ) *result = 
false;
 
  566  if ( mPeriod == rNone ) 
return TQDateTime();
 
  567  if ( mDuration < 0 ) 
return TQDateTime();
 
  568  if ( mDuration == 0 ) {
 
  569    if ( result ) *result = 
true;
 
  575    if ( !buildCache() ) 
return TQDateTime();
 
  577  if ( result ) *result = 
true;
 
  578  return mCachedDateEnd;
 
  611  mByMonthDays.clear();
 
  613  mByWeekNumbers.clear();
 
  621void RecurrenceRule::setDirty()
 
  623  mConstraints.clear();
 
  627  mCachedDates.clear();
 
  628  for ( TQValueList<Observer*>::ConstIterator it = mObservers.begin();
 
  629        it != mObservers.end(); ++it ) {
 
  630    if ( (*it) ) (*it)->recurrenceChanged( 
this );
 
  648void RecurrenceRule::setBySeconds( 
const TQValueList<int> bySeconds )
 
  651  mBySeconds = bySeconds;
 
  655void RecurrenceRule::setByMinutes( 
const TQValueList<int> byMinutes )
 
  658  mByMinutes = byMinutes;
 
  662void RecurrenceRule::setByHours( 
const TQValueList<int> byHours )
 
  670void RecurrenceRule::setByDays( 
const TQValueList<WDayPos> byDays )
 
  677void RecurrenceRule::setByMonthDays( 
const TQValueList<int> byMonthDays )
 
  680  mByMonthDays = byMonthDays;
 
  684void RecurrenceRule::setByYearDays( 
const TQValueList<int> byYearDays )
 
  687  mByYearDays = byYearDays;
 
  691void RecurrenceRule::setByWeekNumbers( 
const TQValueList<int> byWeekNumbers )
 
  694  mByWeekNumbers = byWeekNumbers;
 
  698void RecurrenceRule::setByMonths( 
const TQValueList<int> byMonths )
 
  701  mByMonths = byMonths;
 
  705void RecurrenceRule::setBySetPos( 
const TQValueList<int> bySetPos )
 
  708  mBySetPos = bySetPos;
 
  712void RecurrenceRule::setWeekStart( 
short weekStart )
 
  715  mWeekStart = weekStart;
 
  777void RecurrenceRule::buildConstraints()
 
  779  mTimedRepetition = 0;
 
  780  mNoByRules = mBySetPos.isEmpty();
 
  781  mConstraints.clear();
 
  783  if ( mWeekStart > 0 ) con.weekstart = mWeekStart;
 
  784  mConstraints.append( con );
 
  786  Constraint::List tmp;
 
  787  Constraint::List::const_iterator it;
 
  788  TQValueList<int>::const_iterator intit;
 
  790  #define intConstraint( list, element ) \ 
  791  if ( !list.isEmpty() ) { \ 
  792    mNoByRules = false; \ 
  793    for ( it = mConstraints.constBegin(); it != mConstraints.constEnd(); ++it ) { \ 
  794      for ( intit = list.constBegin(); intit != list.constEnd(); ++intit ) { \ 
  796        con.element = (*intit); \ 
  800    mConstraints = tmp; \ 
  804  intConstraint( mBySeconds, second );
 
  805  intConstraint( mByMinutes, minute );
 
  806  intConstraint( mByHours, hour );
 
  807  intConstraint( mByMonthDays, day );
 
  808  intConstraint( mByMonths, month );
 
  809  intConstraint( mByYearDays, yearday );
 
  810  intConstraint( mByWeekNumbers, weeknumber );
 
  813  if ( !mByDays.isEmpty() ) {
 
  815    for ( it = mConstraints.constBegin(); it != mConstraints.constEnd(); ++it ) {
 
  816      TQValueList<WDayPos>::const_iterator dayit;
 
  817      for ( dayit = mByDays.constBegin(); dayit != mByDays.constEnd(); ++dayit ) {
 
  819        con.weekday = (*dayit).day();
 
  820        con.weekdaynr = (*dayit).pos();
 
  828  #define fixConstraint( element, value ) \ 
  831    for ( it = mConstraints.constBegin(); it != mConstraints.constEnd(); ++it ) { \ 
  832      con = (*it); con.element = value; tmp.append( con ); \ 
  834    mConstraints = tmp; \ 
  840  if ( mPeriod == rWeekly && mByDays.isEmpty() ) {
 
  841    fixConstraint( weekday, mDateStart.date().dayOfWeek() );
 
  848      if ( mByDays.isEmpty() && mByWeekNumbers.isEmpty() && mByYearDays.isEmpty() && mByMonths.isEmpty() ) {
 
  849        fixConstraint( month, mDateStart.date().month() );
 
  852      if ( mByDays.isEmpty() && mByWeekNumbers.isEmpty() && mByYearDays.isEmpty() && mByMonthDays.isEmpty() ) {
 
  853        fixConstraint( day, mDateStart.date().day() );
 
  858      if ( mByHours.isEmpty() ) {
 
  859        fixConstraint( hour, mDateStart.time().hour() );
 
  862      if ( mByMinutes.isEmpty() ) {
 
  863        fixConstraint( minute, mDateStart.time().minute() );
 
  866      if ( mBySeconds.isEmpty() ) {
 
  867        fixConstraint( second, mDateStart.time().second() );
 
  878        mTimedRepetition = mFrequency * 3600;
 
  881        mTimedRepetition = mFrequency * 60;
 
  884        mTimedRepetition = mFrequency;
 
  890    Constraint::List::Iterator conit = mConstraints.begin();
 
  891    while ( conit != mConstraints.end() ) {
 
  892      if ( (*conit).isConsistent( mPeriod ) ) {
 
  895        conit = mConstraints.remove( conit );
 
  901bool RecurrenceRule::buildCache()
 const 
  903kdDebug(5800) << 
"         RecurrenceRule::buildCache: " << endl;
 
  906  Constraint interval( getNextValidDateInterval( 
startDt(), recurrenceType() ) );
 
  909  DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
  910  DateTimeList::Iterator it = dts.begin();
 
  913  while ( it != dts.end() ) {
 
  914    if ( (*it) < 
startDt() ) it =  dts.remove( it );
 
  921  int dtnr = dts.count();
 
  924  while ( loopnr < 10000 && dtnr < mDuration ) {
 
  925    interval.increase( recurrenceType(), 
frequency() );
 
  927    dts += datesForInterval( interval, recurrenceType() );
 
  931  if ( 
int(dts.count()) > mDuration ) {
 
  933    it = dts.at( mDuration );
 
  934    while ( it != dts.end() ) it = dts.remove( it );
 
  939kdDebug(5800) << 
"    Finished Building Cache, cache has " << dts.count() << 
" entries:" << endl;
 
  945  if ( 
int(dts.count()) == mDuration ) {
 
  946    mCachedDateEnd = dts.last();
 
  949    mCachedDateEnd = TQDateTime();
 
  957  for ( Constraint::List::ConstIterator it = mConstraints.begin();
 
  958        it!=mConstraints.end(); ++it ) {
 
  959    match = match || ( (*it).matches( qdt, recurrenceType() ) );
 
  969    if ( qd < mDateStart.date() ) {
 
  974    if ( mDuration >= 0 ) {
 
  975      endDate =  
endDt().date();
 
  976      if ( qd > endDate ) {
 
  984    for ( i = 0, iend = mConstraints.count();  i < iend && !match;  ++i ) {
 
  985      match = mConstraints[i].matches( qd, recurrenceType() );
 
  991    TQDateTime start( qd, TQTime( 0, 0, 0 ) );
 
  992    Constraint interval( getNextValidDateInterval( start, recurrenceType() ) );
 
  995    if ( !interval.matches( qd, recurrenceType() ) ) {
 
 1001    TQDateTime end = start.addDays(1);
 
 1003      DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1004      for ( i = 0, iend = dts.count();  i < iend;  ++i ) {
 
 1005        if ( dts[i].date() >= qd ) {
 
 1006          return dts[i].date() == qd;
 
 1009      interval.increase( recurrenceType(), 
frequency() );
 
 1010    } 
while ( interval.intervalDateTime( recurrenceType() ) < end );
 
 1015  TQDateTime start( qd, TQTime( 0, 0, 0 ) );
 
 1016  TQDateTime end = start.addDays( 1 );
 
 1017  if ( end < mDateStart ) {
 
 1020  if ( start < mDateStart ) {
 
 1025  if ( mDuration >= 0 ) {
 
 1026    TQDateTime endRecur = 
endDt();
 
 1027    if ( endRecur.isValid() ) {
 
 1028      if ( start > endRecur ) {
 
 1031      if ( end > endRecur ) {
 
 1037  if ( mTimedRepetition ) {
 
 1039    int n = 
static_cast<int>( ( mDateStart.secsTo( start ) - 1 ) % mTimedRepetition );
 
 1040    return start.addSecs( mTimedRepetition - n ) < end;
 
 1044  TQDate startDay = start.date();
 
 1045  TQDate endDay = end.addSecs( -1 ).date();
 
 1046  int dayCount = startDay.daysTo( endDay ) + 1;
 
 1051  for ( i = 0, iend = mConstraints.count();  i < iend && !match;  ++i ) {
 
 1052    match = mConstraints[i].matches( startDay, recurrenceType() );
 
 1053    for ( 
int day = 1;  day < dayCount && !match;  ++day ) {
 
 1054      match = mConstraints[i].matches( startDay.addDays( day ), recurrenceType() );
 
 1061  Constraint interval( getNextValidDateInterval( start, recurrenceType() ) );
 
 1065  Constraint intervalm = interval;
 
 1067    match = intervalm.matches( startDay, recurrenceType() );
 
 1068    for ( 
int day = 1;  day < dayCount && !match;  ++day ) {
 
 1069      match = intervalm.matches( startDay.addDays( day ), recurrenceType() );
 
 1074    intervalm.increase( recurrenceType(), 
frequency() );
 
 1075  } 
while ( intervalm.intervalDateTime( recurrenceType() ) < end );
 
 1084    DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1085    int i = findGE( dts, start, 0 );
 
 1087      return dts[i] < end;
 
 1089    interval.increase( recurrenceType(), 
frequency() );
 
 1090  } 
while ( interval.intervalDateTime( recurrenceType() ) < end );
 
 1100  if ( dt < mDateStart ) {
 
 1104  if ( mDuration >= 0 && dt > 
endDt() ) {
 
 1108  if ( mTimedRepetition ) {
 
 1110    return !( mDateStart.secsTo( dt ) % mTimedRepetition );
 
 1120  Constraint interval( getNextValidDateInterval( dt, recurrenceType() ) );
 
 1122  if ( interval.matches( dt, recurrenceType() ) ) {
 
 1134  TQDateTime start( date, TQTime( 0, 0, 0 ) );
 
 1135  TQDateTime end = start.addDays( 1 ).addSecs( -1 );
 
 1137  for ( 
int i = 0, iend = dts.count();  i < iend;  ++i ) {
 
 1138    lst += dts[i].time();
 
 1149  if ( dt < 
startDt() ) 
return 0;
 
 1152  if ( mDuration > 0 && dt >= 
endDt() ) 
return mDuration;
 
 1156  while ( next.isValid() && next <= dt ) {
 
 1169    return TQDateTime();
 
 1173  if ( mDuration > 0 ) {
 
 1174    if ( !mCached ) buildCache();
 
 1175    DateTimeList::ConstIterator it = mCachedDates.begin();
 
 1176    while ( it != mCachedDates.end() && (*it) < afterDate ) {
 
 1180    if ( prev.isValid() && prev < afterDate ) 
return prev;
 
 1181    else return TQDateTime();
 
 1186  if ( mDuration >= 0 && 
endDt().isValid() && afterDate > 
endDt() )
 
 1187    prev = 
endDt().addSecs( 1 );
 
 1189  Constraint interval( getPreviousValidDateInterval( prev, recurrenceType() ) );
 
 1192  DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1193  DateTimeList::Iterator dtit = dts.end();
 
 1194  if ( dtit != dts.begin() ) {
 
 1197    } 
while ( dtit != dts.begin() && (*dtit) >= prev );
 
 1198    if ( (*dtit) < prev ) {
 
 1199      if ( (*dtit) >= 
startDt() ) 
return (*dtit);
 
 1200      else return TQDateTime();
 
 1205  while ( interval.intervalDateTime( recurrenceType() ) > 
startDt() ) {
 
 1206    interval.increase( recurrenceType(), -
frequency() );
 
 1210    DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1212    if ( dts.count() > 0 ) {
 
 1214      if ( prev.isValid() && prev >= 
startDt() ) 
return prev;
 
 1215      else return TQDateTime();
 
 1218  return TQDateTime();
 
 1226  if ( mDuration >= 0 && 
endDt().isValid() && preDate >= 
endDt() )
 
 1227    return TQDateTime();
 
 1230  TQDateTime adjustedPreDate;
 
 1232    adjustedPreDate = 
startDt().addSecs( -1 );
 
 1234    adjustedPreDate = preDate;
 
 1236  if ( mDuration > 0 ) {
 
 1237    if ( !mCached ) buildCache();
 
 1238    DateTimeList::ConstIterator it = mCachedDates.begin();
 
 1239    while ( it != mCachedDates.end() && (*it) <= adjustedPreDate ) ++it;
 
 1240    if ( it != mCachedDates.end() ) {
 
 1247  Constraint interval( getNextValidDateInterval( adjustedPreDate, recurrenceType() ) );
 
 1248  DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1249  DateTimeList::Iterator dtit = dts.begin();
 
 1250  while ( dtit != dts.end() && (*dtit) <= adjustedPreDate ) ++dtit;
 
 1251  if ( dtit != dts.end() ) {
 
 1252    if ( mDuration >= 0 && (*dtit) > 
endDt() ) 
return TQDateTime();
 
 1253    else return (*dtit);
 
 1260  while ( loopnr < 10000 ) {
 
 1261    interval.increase( recurrenceType(), 
frequency() );
 
 1262    DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1263    if ( dts.count() > 0 ) {
 
 1264      TQDateTime ret( dts.first() );
 
 1265      if ( mDuration >= 0 && ret > 
endDt() ) 
return TQDateTime();
 
 1270  return TQDateTime();
 
 1274                                              const TQDateTime &dtEnd )
 const 
 1276  TQDateTime start = dtStart;
 
 1277  TQDateTime end = dtEnd;
 
 1278  DateTimeList result;
 
 1279  if ( end < mDateStart ) {
 
 1282  TQDateTime enddt = end;
 
 1283  if ( mDuration >= 0 ) {
 
 1284    TQDateTime endRecur = 
endDt();
 
 1285    if ( endRecur.isValid() ) {
 
 1286      if ( start > endRecur ) {
 
 1289      if ( end > endRecur ) {
 
 1295  if ( mTimedRepetition ) {
 
 1297    int n = 
static_cast<int>( ( mDateStart.secsTo( start ) - 1 ) % mTimedRepetition );
 
 1298    TQDateTime dt = start.addSecs( mTimedRepetition - n );
 
 1300      n = 
static_cast<int>( ( dt.secsTo( enddt ) - 1 ) / mTimedRepetition ) + 1;
 
 1302      n = TQMIN( n, LOOP_LIMIT );
 
 1303      for ( 
int i = 0;  i < n;  dt = dt.addSecs( mTimedRepetition ), ++i ) {
 
 1310  TQDateTime st = start;
 
 1312  if ( mDuration > 0 ) {
 
 1316    if ( mCachedDateEnd.isValid() && start > mCachedDateEnd ) {
 
 1319    int i = findGE( mCachedDates, start, 0 );
 
 1321      int iend = findGT( mCachedDates, enddt, i );
 
 1323        iend = mCachedDates.count();
 
 1327      while ( i < iend ) {
 
 1328        result += mCachedDates[i++];
 
 1331    if ( mCachedDateEnd.isValid() ) {
 
 1333    } 
else if ( !result.isEmpty() ) {
 
 1334      result += TQDateTime();    
 
 1341    st = mCachedLastDate.addSecs( 1 );
 
 1344  Constraint interval( getNextValidDateInterval( st, recurrenceType() ) );
 
 1347    DateTimeList dts = datesForInterval( interval, recurrenceType() );
 
 1349    int iend = dts.count();
 
 1351      i = findGE( dts, st, 0 );
 
 1356    int j = findGT( dts, enddt, i );
 
 1361    while ( i < iend ) {
 
 1365    interval.increase( recurrenceType(), 
frequency() );
 
 1366  } 
while ( ++loop < LOOP_LIMIT &&
 
 1367            interval.intervalDateTime( recurrenceType() ) < end );
 
 1371RecurrenceRule::Constraint RecurrenceRule::getPreviousValidDateInterval( 
const TQDateTime &preDate, PeriodType type )
 const 
 1375  TQDateTime nextValid = 
startDt();
 
 1378  TQDateTime toDate( preDate );
 
 1389    case rHourly:   modifier *= 60;
 
 1390    case rMinutely: modifier *= 60;
 
 1392        periods = ownSecsTo( start, toDate ) / modifier;
 
 1395        nextValid = start.addSecs( modifier * periods );
 
 1399        toDate = toDate.addDays( -(7 + toDate.date().dayOfWeek() - mWeekStart) % 7 );
 
 1400        start = start.addDays( -(7 + start.date().dayOfWeek() - mWeekStart) % 7 );
 
 1403        periods = start.daysTo( toDate ) / modifier;
 
 1406        nextValid = start.addDays( modifier * periods );
 
 1410        periods = 12*( toDate.date().year() - start.date().year() ) +
 
 1411             ( toDate.date().month() - start.date().month() );
 
 1416        start.setDate( TQDate( start.date().year(), start.date().month(), 1 ) );
 
 1417        nextValid.setDate( start.date().addMonths( periods ) );
 
 1420        periods = ( toDate.date().year() - start.date().year() );
 
 1423        nextValid.setDate( start.date().addYears( periods ) );
 
 1430  return Constraint( nextValid, type, mWeekStart );
 
 1433RecurrenceRule::Constraint RecurrenceRule::getNextValidDateInterval( 
const TQDateTime &preDate, PeriodType type )
 const 
 1436  kdDebug(5800) << 
"       (o) getNextValidDateInterval after " << preDate << 
", type=" << type << endl;
 
 1439  TQDateTime nextValid( start );
 
 1441  TQDateTime toDate( preDate );
 
 1452    case rHourly:   modifier *= 60;
 
 1453    case rMinutely: modifier *= 60;
 
 1455        periods = ownSecsTo( start, toDate ) / modifier;
 
 1456        periods = TQMAX( 0, periods);
 
 1459        nextValid = start.addSecs( modifier * periods );
 
 1464        toDate = toDate.addDays( -(7 + toDate.date().dayOfWeek() - mWeekStart) % 7 );
 
 1465        start = start.addDays( -(7 + start.date().dayOfWeek() - mWeekStart) % 7 );
 
 1468        periods = start.daysTo( toDate ) / modifier;
 
 1469        periods = TQMAX( 0, periods);
 
 1472        nextValid = start.addDays( modifier * periods );
 
 1476        periods = 12*( toDate.date().year() - start.date().year() ) +
 
 1477             ( toDate.date().month() - start.date().month() );
 
 1478        periods = TQMAX( 0, periods);
 
 1483        start.setDate( TQDate( start.date().year(), start.date().month(), 1 ) );
 
 1484        nextValid.setDate( start.date().addMonths( periods ) );
 
 1487        periods = ( toDate.date().year() - start.date().year() );
 
 1488        periods = TQMAX( 0, periods);
 
 1491        nextValid.setDate( start.date().addYears( periods ) );
 
 1498  return Constraint( nextValid, type, mWeekStart );
 
 1501bool RecurrenceRule::mergeIntervalConstraint( Constraint *merged,
 
 1502          const Constraint &conit, 
const Constraint &interval )
 const 
 1504  Constraint result( interval );
 
 1506#define mergeConstraint( name, cmparison ) \ 
 1507  if ( conit.name cmparison ) { \ 
 1508    if ( !(result.name cmparison) || result.name == conit.name ) { \ 
 1509      result.name = conit.name; \ 
 1510    } else return false;\ 
 1513  mergeConstraint( year, > 0 );
 
 1514  mergeConstraint( month, > 0 );
 
 1515  mergeConstraint( day, != 0 );
 
 1516  mergeConstraint( hour, >= 0 );
 
 1517  mergeConstraint( minute, >= 0 );
 
 1518  mergeConstraint( second, >= 0 );
 
 1520  mergeConstraint( weekday, != 0 );
 
 1521  mergeConstraint( weekdaynr, != 0 );
 
 1522  mergeConstraint( weeknumber, != 0 );
 
 1523  mergeConstraint( yearday, != 0 );
 
 1525  #undef mergeConstraint 
 1526  if ( merged ) *merged = result;
 
 1531DateTimeList RecurrenceRule::datesForInterval( 
const Constraint &interval, PeriodType type )
 const 
 1542  Constraint::List::ConstIterator conit = mConstraints.begin();
 
 1543  for ( ; conit != mConstraints.end(); ++conit ) {
 
 1545    bool mergeok = mergeIntervalConstraint( &merged, *conit, interval );
 
 1547    if ( merged.year <= 0 || merged.hour < 0 || merged.minute < 0 || merged.second < 0 )
 
 1554      DateTimeList lstnew = merged.dateTimes( type );
 
 1571  if ( !mBySetPos.isEmpty() ) {
 
 1572    DateTimeList tmplst = lst;
 
 1574    TQValueList<int>::ConstIterator it;
 
 1575    for ( it = mBySetPos.begin(); it != mBySetPos.end(); ++it ) {
 
 1577      if ( pos > 0 ) --pos;
 
 1578      if ( pos < 0 ) pos += tmplst.count();
 
 1579      if ( pos >= 0 && uint(pos) < tmplst.count() ) {
 
 1580        lst.append( tmplst[pos] );
 
 1593  kdDebug(5800) << 
"RecurrenceRule::dump():" << endl;
 
 1594  if ( !mRRule.isEmpty() )
 
 1595    kdDebug(5800) << 
"   RRULE=" << mRRule << endl;
 
 1596  kdDebug(5800) << 
"   Read-Only: " << 
isReadOnly() <<
 
 1597                   ", dirty: " << mDirty << endl;
 
 1599  kdDebug(5800) << 
"   Period type: " << recurrenceType() << 
", frequency: " << 
frequency() << endl;
 
 1600  kdDebug(5800) << 
"   #occurrences: " << 
duration() << endl;
 
 1601  kdDebug(5800) << 
"   start date: " << 
startDt() <<
", end date: " << 
endDt() << endl;
 
 1604#define dumpByIntList(list,label) \ 
 1605  if ( !list.isEmpty() ) {\ 
 1607    for ( TQValueList<int>::ConstIterator it = list.begin();\ 
 1608          it != list.end(); ++it ) {\ 
 1609      lst.append( TQString::number( *it ) );\ 
 1611    kdDebug(5800) << "   " << label << lst.join(", ") << endl;\
 
 1613  dumpByIntList( mBySeconds,    
"BySeconds:  " );
 
 1614  dumpByIntList( mByMinutes,    
"ByMinutes:  " );
 
 1615  dumpByIntList( mByHours,      
"ByHours:    " );
 
 1616  if ( !mByDays.isEmpty() ) {
 
 1618    for ( TQValueList<WDayPos>::ConstIterator it = mByDays.begin();
 
 1619          it != mByDays.end(); ++it ) {
 
 1620      lst.append( ( ((*it).pos()!=0) ? TQString::number( (*it).pos() ) : 
"" ) +
 
 1621                   DateHelper::dayName( (*it).day() ) );
 
 1623    kdDebug(5800) << 
"   ByDays:     " << lst.join(
", ") << endl;
 
 1625  dumpByIntList( mByMonthDays,  
"ByMonthDays:" );
 
 1626  dumpByIntList( mByYearDays,   
"ByYearDays: " );
 
 1627  dumpByIntList( mByWeekNumbers,
"ByWeekNr:   " );
 
 1628  dumpByIntList( mByMonths,     
"ByMonths:   " );
 
 1629  dumpByIntList( mBySetPos,     
"BySetPos:   " );
 
 1630  #undef dumpByIntList 
 1632  kdDebug(5800) << 
"   Week start: " << DateHelper::dayName( mWeekStart ) << endl;
 
 1634  kdDebug(5800) << 
"   Constraints:" << endl;
 
 1636  for ( Constraint::List::ConstIterator it = mConstraints.begin();
 
 1637        it!=mConstraints.end(); ++it ) {
 
 1643void RecurrenceRule::Constraint::dump()
 const 
 1645  kdDebug(5800) << 
"     ~> Y="<<year<<
", M="<<month<<
", D="<<day<<
", H="<<hour<<
", m="<<minute<<
", S="<<second<<
", wd="<<weekday<<
",#wd="<<weekdaynr<<
", #w="<<weeknumber<<
", yd="<<yearday<<endl;
 
This class represents a recurrence rule for a calendar incidence.
 
TQDateTime getPreviousDate(const TQDateTime &afterDateTime) const
Returns the date and time of the last previous recurrence, before the specified date/time.
 
TQDateTime endDt(bool *result=0) const
Returns the date and time of the last recurrence.
 
TimeList recurTimesOn(const TQDate &date) const
Returns a list of the times on the specified date at which the recurrence will occur.
 
void clear()
Turns off recurrence for the event.
 
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last.
 
int durationTo(const TQDateTime &) const
Returns the number of recurrences up to and including the date/time specified.
 
void dump() const
Debug output.
 
TQDateTime startDt() const
Return the start of the recurrence.
 
bool recursOn(const TQDate &qd) const
Returns true if the date specified is one on which the event will recur.
 
void setFrequency(int freq)
Sets the frequency of recurrence, in terms of the recurrence time period type.
 
void removeObserver(Observer *observer)
Removes an observer that was added with addObserver.
 
void setFloats(bool floats)
Sets whether the dtstart is a floating time (i.e.
 
void setEndDt(const TQDateTime &endDateTime)
Sets the date and time of the last recurrence.
 
bool recursAt(const TQDateTime &) const
Returns true if the date/time specified is one at which the event will recur.
 
uint frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
 
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
 
bool dateMatchesRules(const TQDateTime &qdt) const
Returns true if the date matches the rules.
 
void addObserver(Observer *observer)
Installs an observer.
 
bool doesFloat() const
Returns whether the start date has no time associated.
 
PeriodType
enum for describing the frequency how an event recurs, if at all.
 
bool isReadOnly() const
Returns true if the recurrence is read-only, or false if it can be changed.
 
TQDateTime getNextDate(const TQDateTime &preDateTime) const
Returns the date and time of the next recurrence, after the specified date/time.
 
DateTimeList timesInInterval(const TQDateTime &start, const TQDateTime &end) const
Returns a list of all the times at which the recurrence will occur between two specified times.
 
void setStartDt(const TQDateTime &start)
Set start of recurrence, as a date and time.
 
Namespace KCal is for global classes, objects and/or functions in libkcal.