23 #include <tqbitarray.h>
26 #include <libkcal/icalformat.h>
30 #include "karecurrence.h"
51 KARecurrence::Feb29Type KARecurrence::mDefaultFeb29 = KARecurrence::FEB29_FEB29;
60 bool KARecurrence::set(Type recurType,
int freq,
int count,
int f29,
const DateTime& start,
const TQDateTime& end)
66 case MINUTELY: rrtype = RecurrenceRule::rMinutely;
break;
67 case DAILY: rrtype = RecurrenceRule::rDaily;
break;
68 case WEEKLY: rrtype = RecurrenceRule::rWeekly;
break;
69 case MONTHLY_DAY: rrtype = RecurrenceRule::rMonthly;
break;
70 case ANNUAL_DATE: rrtype = RecurrenceRule::rYearly;
break;
71 case NO_RECUR: rrtype = RecurrenceRule::rNone;
break;
75 if (!init(rrtype, freq, count, f29, start, end))
82 days.setBit(start.date().dayOfWeek() - 1);
87 addMonthlyDate(start.date().day());
90 addYearlyDate(start.date().day());
91 addYearlyMonth(start.date().month());
104 const TQDateTime& end)
107 Feb29Type feb29Type = (f29 == -1) ? mDefaultFeb29 :
static_cast<Feb29Type
>(f29);
108 mFeb29Type = FEB29_FEB29;
112 bool dateOnly = start.isDateOnly();
113 if (!count && ((!dateOnly && !end.isValid())
114 || (dateOnly && !end.date().isValid())))
118 case RecurrenceRule::rMinutely:
119 case RecurrenceRule::rDaily:
120 case RecurrenceRule::rWeekly:
121 case RecurrenceRule::rMonthly:
122 case RecurrenceRule::rYearly:
129 setNewRecurrenceType(recurType, freq);
133 setEndDate(end.date());
136 TQDateTime startdt = start.dateTime();
137 if ((recurType == RecurrenceRule::rYearly
138 && feb29Type == FEB29_FEB28) || feb29Type == FEB29_MAR1)
140 int year = startdt.date().year();
141 if (!TQDate::leapYear(year)
142 && startdt.date().dayOfYear() == (feb29Type == FEB29_MAR1 ? 60 : 59))
151 while (!TQDate::leapYear(--year)) ;
152 startdt.setDate(TQDate(year, 2, 29));
154 mFeb29Type = feb29Type;
157 setStartDate(startdt.date());
159 setStartDateTime(startdt);
166 bool KARecurrence::set(
const TQString& icalRRULE)
168 static TQString RRULE = TQString::fromLatin1(
"RRULE:");
171 if (icalRRULE.isEmpty())
175 (icalRRULE.startsWith(RRULE) ? icalRRULE.mid(RRULE.length()) : icalRRULE)))
190 void KARecurrence::fix()
193 mFeb29Type = FEB29_FEB29;
195 int days[2] = { 0, 0 };
197 RecurrenceRule::List rrulelist = rRules();
198 RecurrenceRule::List::ConstIterator rr = rrulelist.begin();
199 for (
int i = 0; i < 2 && rr != rrulelist.end(); ++i, ++rr)
204 int rtype = recurrenceType(rrule);
209 rrule->setRecurrenceType(RecurrenceRule::rMinutely);
222 if (dailyType(rrule))
236 || rrule->
frequency() != rrules[0]->frequency()
237 || rrule->
startDt() != rrules[0]->startDt())
240 TQValueList<int> ds = rrule->byYearDays();
241 if (!ds.isEmpty() && ds.first() == 60)
252 TQValueList<int> ds = rrule->byMonthDays();
255 int day = ds.first();
260 if (day == days[0] || (day == -1 && days[0] == 60)
261 || rrule->
frequency() != rrules[0]->frequency()
262 || rrule->
startDt() != rrules[0]->startDt())
269 rrule->setByMonthDays(ds);
274 TQValueList<int> months = rrule->byMonths();
275 if (months.count() != 1 || months.first() != 2)
278 if (day == 29 || day == -1)
298 for ( ; rr != rrulelist.end(); ++rr)
306 TQValueList<int> months;
316 rrules[0] = rrules[1];
323 months = rrules[0]->byMonths();
324 if (months.remove(2))
325 rrules[0]->setByMonths(months);
327 count = combineDurations(rrules[0], rrules[1], end);
328 mFeb29Type = (days[1] == 60) ? FEB29_MAR1 : FEB29_FEB28;
330 else if (convert == 1 && days[0] == 60)
337 mFeb29Type = FEB29_MAR1;
343 setNewRecurrenceType(RecurrenceRule::rYearly, frequency());
346 rrule->setByMonths(months);
349 rrule->setByMonthDays(ds);
359 TQDateTime KARecurrence::getNextDateTime(
const TQDateTime& preDateTime)
const
367 writeRecurrence(recur);
378 TQDateTime KARecurrence::getPreviousDateTime(
const TQDateTime& afterDateTime)
const
386 writeRecurrence(recur);
402 recur.setExDates(exDates());
403 recur.setExDateTimes(exDateTimes());
407 int freq = frequency();
408 int count = duration();
409 static_cast<KARecurrence*
>(&recur)->setNewRecurrenceType(rrule->recurrenceType(), freq);
417 if (rrule->byDays().isEmpty())
422 recur.defaultRRule(
true)->setByDays(rrule->byDays());
425 recur.defaultRRule(
true)->setByMonthDays(rrule->byMonthDays());
428 recur.defaultRRule(
true)->setByMonths(rrule->byMonths());
429 recur.defaultRRule()->setByDays(rrule->byDays());
433 TQValueList<int> months = rrule->byMonths();
434 TQValueList<int> days = monthDays();
435 bool special = (mFeb29Type != FEB29_FEB29 && !days.isEmpty()
436 && days.first() == 29 && months.remove(2));
438 rrule1->setByMonths(months);
439 rrule1->setByMonthDays(days);
446 rrule2->setRecurrenceType(RecurrenceRule::rYearly);
452 if (mFeb29Type == FEB29_MAR1)
456 rrule2->setByYearDays(ds);
462 rrule2->setByMonthDays(ds);
465 rrule2->setByMonths(ms);
468 if (months.isEmpty())
495 TQDateTime end = endDateTime();
496 kdDebug()<<
"29th recurrence: count="<<count<<
", end date="<<end.toString()<<endl;
498 - (rrule1->
recursOn(startDate()) ? 0 : 1);
504 - (rrule2->
recursOn(startDate()) ? 0 : 1);
512 recur.addRRule(rrule2);
523 TQDateTime KARecurrence::endDateTime()
const
525 if (mFeb29Type == FEB29_FEB29 || duration() <= 1)
541 rrule->setRecurrenceType(RecurrenceRule::rYearly);
542 TQDateTime dt = startDateTime();
543 TQDate d = dt.date();
549 d.setYMD(d.year(), d.month(), 28);
552 if (d.month() != 2 || mFeb29Type != FEB29_FEB28 || TQDate::leapYear(d.year()))
555 d.setYMD(d.year(), d.month(), 27);
559 if (d.month() == 3 && mFeb29Type == FEB29_MAR1 && !TQDate::leapYear(d.year()))
563 d.setYMD(d.year(), 2, 28);
576 rrule->setByMonthDays(ds);
577 rrule->setByMonths(defaultRRuleConst()->byMonths());
583 if (mFeb29Type == FEB29_FEB28 && dt.date().month() == 2 && !TQDate::leapYear(dt.date().year()))
585 return dt.addDays(1);
591 TQDate KARecurrence::endDate()
const
593 TQDateTime end = endDateTime();
594 return end.isValid() ? end.date() : TQDate();
601 bool KARecurrence::recursOn(
const TQDate& dt)
const
605 if (dt != startDate())
609 if (rDates().contains(dt))
611 RecurrenceRule::List rulelist = rRules();
612 for (RecurrenceRule::List::ConstIterator rr = rulelist.begin(); rr != rulelist.end(); ++rr)
613 if ((*rr)->recursOn(dt))
615 DateTimeList dtlist = rDateTimes();
616 for (DateTimeList::ConstIterator rdt = dtlist.begin(); rdt != dtlist.end(); ++rdt)
617 if ((*rdt).date() == dt)
630 if (count1 == -1 && count2 == -1)
635 if (count1 && !count2 && rrule2->
endDt().date() == startDateTime().date())
637 if (count2 && !count1 && rrule1->
endDt().date() == startDateTime().date())
644 if (!count1 || !count2)
647 TQDateTime end1 = rrule1->
endDt();
648 TQDateTime end2 = rrule2->
endDt();
649 if (end1.date() == end2.date())
652 return count1 + count2;
657 && (!end1.isValid() || end1.date() > end2.date()))
675 TQDateTime next1(rr.getNextDate(end1).date());
676 if (!next1.isValid())
680 if (end2.isValid() && next1 > end2)
686 return count1 + count2;
689 end = (prev2 > end1.date()) ? prev2 : end1.date();
693 return count1 + count2;
700 int KARecurrence::longestInterval()
const
702 int freq = frequency();
710 TQValueList<RecurrenceRule::WDayPos> days = defaultRRuleConst()->byDays();
716 bool ds[7] = {
false,
false,
false,
false,
false,
false,
false };
717 for (TQValueList<RecurrenceRule::WDayPos>::ConstIterator it = days.begin(); it != days.end(); ++it)
718 if ((*it).pos() == 0)
719 ds[(*it).day() - 1] =
true;
727 for (
int i = 0; i < freq*7; i += freq)
733 else if (i - last > maxgap)
738 int wrap = freq*7 - last + first;
741 return maxgap * 1440;
747 return ds[startDate().dayOfWeek() - 1] ? freq * 1440 : 0;
754 TQBitArray ds = days();
758 for (
int i = 0; i < 7; ++i)
760 if (ds.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1))
764 else if (i - last > maxgap)
771 int span = last - first;
773 return (freq*7 - span) * 1440;
774 if (7 - span > maxgap)
775 return (7 - span) * 1440;
776 return maxgap * 1440;
780 return freq * 1440 * 31;
787 const TQValueList<int> months = yearMonths();
788 if (months.isEmpty())
790 if (months.count() == 1)
791 return freq * 1440 * 365;
795 for (TQValueListConstIterator<int> it = months.begin(); it != months.end(); ++it)
801 int span = TQDate(2001, last, 1).daysTo(TQDate(2001, *it, 1));
807 int span = TQDate(2001, first, 1).daysTo(TQDate(2001, last, 1));
809 return (freq*365 - span) * 1440;
810 if (365 - span > maxgap)
811 return (365 - span) * 1440;
812 return maxgap * 1440;
823 KARecurrence::Type KARecurrence::type()
const
825 if (mCachedType == -1)
826 mCachedType = type(defaultRRuleConst());
827 return static_cast<Type
>(mCachedType);
830 KARecurrence::Type KARecurrence::type(
const RecurrenceRule* rrule)
832 switch (recurrenceType(rrule))
834 case rMinutely:
return MINUTELY;
835 case rDaily:
return DAILY;
836 case rWeekly:
return WEEKLY;
837 case rMonthlyDay:
return MONTHLY_DAY;
838 case rMonthlyPos:
return MONTHLY_POS;
839 case rYearlyMonth:
return ANNUAL_DATE;
840 case rYearlyPos:
return ANNUAL_POS;
842 if (dailyType(rrule))
853 if (rrule->recurrenceType() != RecurrenceRule::rDaily
854 || !rrule->bySeconds().isEmpty()
855 || !rrule->byMinutes().isEmpty()
856 || !rrule->byHours().isEmpty()
857 || !rrule->byWeekNumbers().isEmpty()
858 || !rrule->byMonthDays().isEmpty()
859 || !rrule->byMonths().isEmpty()
860 || !rrule->bySetPos().isEmpty()
861 || !rrule->byYearDays().isEmpty())
863 TQValueList<RecurrenceRule::WDayPos> days = rrule->byDays();
868 for (TQValueList<RecurrenceRule::WDayPos>::ConstIterator it = days.begin(); it != days.end(); ++it)
870 if ((*it).pos() != 0)
TQDateTime getPreviousDate(const TQDateTime &afterDateTime) const
TQDateTime endDt(bool *result=0) const
void setDuration(int duration)
int durationTo(const TQDateTime &) const
TQDateTime startDt() const
bool recursOn(const TQDate &qd) const
void setFrequency(int freq)
void setFloats(bool floats)
void setEndDt(const TQDateTime &endDateTime)
void setStartDt(const TQDateTime &start)
TQDateTime endDateTime() const
void setEndDateTime(const TQDateTime &endDateTime)
void setStartDateTime(const TQDateTime &start)
TQDateTime getPreviousDateTime(const TQDateTime &afterDateTime) const
bool recursOn(const TQDate &qd) const
void setDuration(int duration)
TQDateTime getNextDateTime(const TQDateTime &preDateTime) const