summaryrefslogtreecommitdiffabout
path: root/libkcal/recurrence.cpp
Side-by-side diff
Diffstat (limited to 'libkcal/recurrence.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/recurrence.cpp34
1 files changed, 11 insertions, 23 deletions
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index 8a175c9..6ee5499 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -723,825 +723,822 @@ void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
return;
if (mCompatVersion < 310)
mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
}
void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
mCompatDuration = 0;
setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
}
void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
{
if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
return;
if (mCompatVersion < 310)
mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
}
void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
{
if (mRecurReadOnly) return;
rEndDateTime.setDate(_rEndDate);
rEndDateTime.setTime(mRecurStart.time());
mCompatDuration = 0;
setYearly_(rYearlyMonth, type, _rFreq, 0);
}
void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
{
if (recurs == rYearlyPos)
addMonthlyPos_(_rPos, _rDays);
}
const QPtrList<int> &Recurrence::yearNums() const
{
return rYearNums;
}
void Recurrence::addYearlyMonth(short _rPos )
{
if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
return;
rMonthPos *tmpPos = new rMonthPos;
if ( _rPos > 0) {
tmpPos->rPos = _rPos;
tmpPos->negative = false;
} else {
tmpPos->rPos = -_rPos; // take abs()
tmpPos->negative = true;
}
rMonthPositions.append(tmpPos);
}
void Recurrence::addYearlyNum(short _rNum)
{
if (mRecurReadOnly
|| (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
|| _rNum <= 0) // invalid day/month number
return;
if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) {
// Backwards compatibility for KDE < 3.1.
// Dates were stored as day numbers, with a fiddle to take account of leap years.
// Convert the day number to a month.
if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366))
return; // invalid day number
_rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month();
} else
if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12
|| recurs == rYearlyDay && _rNum > 366)
return; // invalid day number
uint i = 0;
for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) {
if (_rNum == *it)
return; // this day/month is already in the list - avoid duplication
++i;
}
int *tmpNum = new int;
*tmpNum = _rNum;
rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position
if (mCompatVersion < 310 && mCompatDuration > 0) {
// Backwards compatibility for KDE < 3.1.
// rDuration was set to the number of time periods to recur.
// Convert this to the number of occurrences.
QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31);
rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
rDuration = recurCalc(COUNT_TO_DATE, end);
}
if (mParent) mParent->updated();
}
QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const
{
if (last)
*last = false;
int freq;
switch (recurs)
{
case rMinutely:
freq = rFreq * 60;
break;
case rHourly:
freq = rFreq * 3600;
break;
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos: {
QDate preDate = preDateTime.date();
if (!mFloats && mRecurStart.time() > preDateTime.time())
preDate = preDate.addDays(-1);
return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time());
}
default:
return QDateTime();
}
// It's a sub-daily recurrence
if (preDateTime < mRecurStart)
return mRecurStart;
int count = mRecurStart.secsTo(preDateTime) / freq + 2;
if (rDuration > 0) {
if (count > rDuration)
return QDateTime();
if (last && count == rDuration)
*last = true;
}
QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
if (rDuration == 0) {
if (endtime > rEndDateTime)
return QDateTime();
if (last && endtime == rEndDateTime)
*last = true;
}
return endtime;
}
QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const
{
if (last)
*last = false;
switch (recurs)
{
case rMinutely:
case rHourly:
return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date();
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos:
qDebug("Recurrence::getNextDate: MAY BE BROKEN ");
return getNextDateNoTime(preDate, last);
default:
return QDate();
}
}
QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const
{
if (last)
*last = false;
int freq;
switch (recurs)
{
case rMinutely:
freq = rFreq * 60;
break;
case rHourly:
freq = rFreq * 3600;
break;
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos: {
QDate afterDate = afterDateTime.date();
if (!mFloats && mRecurStart.time() < afterDateTime.time())
afterDate = afterDate.addDays(1);
return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time());
}
default:
return QDateTime();
}
// It's a sub-daily recurrence
if (afterDateTime <= mRecurStart)
return QDateTime();
int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1;
if (rDuration > 0) {
if (count > rDuration)
count = rDuration;
if (last && count == rDuration)
*last = true;
}
QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
if (rDuration == 0) {
if (endtime > rEndDateTime)
endtime = rEndDateTime;
if (last && endtime == rEndDateTime)
*last = true;
}
return endtime;
}
QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const
{
if (last)
*last = false;
switch (recurs)
{
case rMinutely:
case rHourly:
return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date();
case rDaily:
case rWeekly:
case rMonthlyPos:
case rMonthlyDay:
case rYearlyMonth:
case rYearlyDay:
case rYearlyPos:
return getPreviousDateNoTime(afterDate, last);
default:
return QDate();
}
}
/***************************** PROTECTED FUNCTIONS ***************************/
bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const
{
if ((qd >= mRecurStart.date()) &&
((rDuration > 0) && (qd <= endDate()) ||
((rDuration == 0) && (qd <= rEndDateTime.date())) ||
(rDuration == -1))) {
// The date queried falls within the range of the event.
if (secondFreq < 24*3600)
return true; // the event recurs at least once each day
- int after = mRecurStart.secsTo(QDateTime(qd));
+ int after = mRecurStart.secsTo(QDateTime(qd)) - 1;
if (after / secondFreq != (after + 24*3600) / secondFreq)
return true;
}
return false;
}
bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const
{
if ((dt >= mRecurStart) &&
((rDuration > 0) && (dt <= endDateTime()) ||
((rDuration == 0) && (dt <= rEndDateTime)) ||
(rDuration == -1))) {
// The time queried falls within the range of the event.
if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0)
return true;
}
return false;
}
bool Recurrence::recursDaily(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
if ((dStart.daysTo(qd) % rFreq) == 0) {
// The date is a day which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
return true;
}
}
return false;
}
bool Recurrence::recursWeekly(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
if ((dStart.daysTo(qd)/7) % rFreq == 0) {
// The date is in a week which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
// check if the bits set match today.
int i = qd.dayOfWeek()-1;
if (rDays.testBit((uint) i))
return true;
}
}
return false;
}
bool Recurrence::recursMonthly(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
int year = qd.year();
int month = qd.month();
int day = qd.day();
// calculate how many months ahead this date is from the original
// event's date
int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month());
if ((monthsAhead % rFreq) == 0) {
// The date is in a month which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
QValueList<int> days;
int daysInMonth = qd.daysInMonth();
if (recurs == rMonthlyDay)
getMonthlyDayDays(days, daysInMonth);
else if (recurs == rMonthlyPos)
getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek());
for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
if (*it == day)
return true;
}
// no dates matched
}
}
return false;
}
bool Recurrence::recursYearlyByMonth(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
int startDay = dStart.day();
int qday = qd.day();
int qmonth = qd.month();
int qyear = qd.year();
bool match = (qday == startDay);
if (!match && startDay == 29 && dStart.month() == 2) {
// It's a recurrence on February 29th
switch (mFeb29YearlyType) {
case rFeb28:
if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear))
match = true;
break;
case rMar1:
if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) {
qmonth = 2;
match = true;
}
break;
case rFeb29:
break;
}
}
if (match) {
// The day of the month matches. Calculate how many years ahead
// this date is from the original event's date.
int yearsAhead = (qyear - dStart.year());
if (yearsAhead % rFreq == 0) {
// The date is in a year which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
int i = qmonth;
for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
if (i == *qlin.current())
return true;
}
}
}
}
return false;
}
bool Recurrence::recursYearlyByPos(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
int year = qd.year();
int month = qd.month();
int day = qd.day();
// calculate how many years ahead this date is from the original
// event's date
int yearsAhead = (year - dStart.year());
if (yearsAhead % rFreq == 0) {
// The date is in a year which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
if (month == *qlin.current()) {
// The month recurs
QValueList<int> days;
getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek());
for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
if (*it == day)
return true;
}
}
}
}
}
return false;
}
bool Recurrence::recursYearlyByDay(const QDate &qd) const
{
QDate dStart = mRecurStart.date();
// calculate how many years ahead this date is from the original
// event's date
int yearsAhead = (qd.year() - dStart.year());
if (yearsAhead % rFreq == 0) {
// The date is in a year which recurs
if (qd >= dStart
&& ((rDuration > 0 && qd <= endDate()) ||
(rDuration == 0 && qd <= rEndDateTime.date()) ||
rDuration == -1)) {
// The date queried falls within the range of the event.
int i = qd.dayOfYear();
for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
if (i == *qlin.current())
return true;
}
}
}
return false;
}
/* Get the date of the next recurrence, after the specified date.
* If 'last' is non-null, '*last' is set to true if the next recurrence is the
* last recurrence, else false.
* Reply = date of next recurrence, or invalid date if none.
*/
QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const
{
if (last)
*last = false;
QDate dStart = mRecurStart.date();
if (preDate < dStart)
return dStart;
QDate earliestDate = preDate.addDays(1);
QDate nextDate;
switch (recurs) {
case rDaily:
nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq);
break;
case rWeekly: {
- QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
+ QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart
int earliestDayOfWeek = earliestDate.dayOfWeek();
int weeksAhead = start.daysTo(earliestDate) / 7;
int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
weeksAhead -= notThisWeek; // latest week which recurred
int weekday = 0;
// First check for any remaining day this week, if this week is a recurring week
if (!notThisWeek)
weekday = getFirstDayInWeek(earliestDayOfWeek);
// Check for a day in the next scheduled week
- if (!weekday && earliestDayOfWeek > 1)
+ if (!weekday )
weekday = getFirstDayInWeek(rWeekStart) + rFreq*7;
- if (weekday)
- nextDate = start.addDays(weeksAhead*7 + weekday - 1);
+ nextDate = start.addDays(weeksAhead*7 + weekday - 1);
break;
}
case rMonthlyDay:
case rMonthlyPos: {
int startYear = dStart.year();
int startMonth = dStart.month(); // 1..12
int earliestYear = earliestDate.year();
int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth;
int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
monthsAhead -= notThisMonth; // latest month which recurred
// Check for the first later day in the current month
if (!notThisMonth)
nextDate = getFirstDateInMonth(earliestDate);
- if (!nextDate.isValid() && earliestDate.day() > 1) {
+ if (!nextDate.isValid() ) {
// Check for a day in the next scheduled month
int months = startMonth - 1 + monthsAhead + rFreq;
nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1));
}
break;
}
case rYearlyMonth:
case rYearlyPos:
case rYearlyDay: {
int startYear = dStart.year();
int yearsAhead = earliestDate.year() - startYear;
int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
yearsAhead -= notThisYear; // latest year which recurred
// Check for the first later date in the current year
if (!notThisYear)
nextDate = getFirstDateInYear(earliestDate);
// Check for a date in the next scheduled year
if (!nextDate.isValid() && earliestDate.dayOfYear() > 1)
nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1));
break;
}
case rNone:
default:
return QDate();
}
if (rDuration >= 0 && nextDate.isValid()) {
// Check that the date found is within the range of the recurrence
QDate end = endDate();
if (nextDate > end)
return QDate();
if (last && nextDate == end)
*last = true;
}
return nextDate;
}
/* Get the date of the last previous recurrence, before the specified date.
* Reply = date of previous recurrence, or invalid date if none.
*/
QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const
{
if (last)
*last = false;
QDate dStart = mRecurStart.date();
QDate latestDate = afterDate.addDays(-1);
if (latestDate < dStart)
return QDate();
QDate prevDate;
switch (recurs) {
case rDaily:
prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq);
break;
case rWeekly: {
- QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
- int latestDayOfWeek = latestDate.dayOfWeek();
+ QDate start = dStart.addDays(-((dStart.dayOfWeek() - rWeekStart + 7)%7)); // start of week for dStart
+ int latestDayOfWeek = latestDate.dayOfWeek();
int weeksAhead = start.daysTo(latestDate) / 7;
int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
weeksAhead -= notThisWeek; // latest week which recurred
int weekday = 0;
// First check for any previous day this week, if this week is a recurring week
if (!notThisWeek)
weekday = getLastDayInWeek(latestDayOfWeek);
// Check for a day in the previous scheduled week
if (!weekday) {
+ if (!notThisWeek)
+ weeksAhead -= rFreq;
int weekEnd = (rWeekStart + 5)%7 + 1;
- if (latestDayOfWeek < weekEnd) {
- if (!notThisWeek)
- weeksAhead -= rFreq;
- weekday = getLastDayInWeek(weekEnd);
- }
+ weekday = getLastDayInWeek(weekEnd);
}
if (weekday)
prevDate = start.addDays(weeksAhead*7 + weekday - 1);
break;
}
case rMonthlyDay:
case rMonthlyPos: {
int startYear = dStart.year();
int startMonth = dStart.month(); // 1..12
int latestYear = latestDate.year();
int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth;
int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
monthsAhead -= notThisMonth; // latest month which recurred
// Check for the last earlier day in the current month
if (!notThisMonth)
prevDate = getLastDateInMonth(latestDate);
if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) {
// Check for a day in the previous scheduled month
if (!notThisMonth)
monthsAhead -= rFreq;
int months = startMonth + monthsAhead; // get the month after the one that recurs
prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1));
}
break;
}
case rYearlyMonth:
case rYearlyPos:
case rYearlyDay: {
int startYear = dStart.year();
int yearsAhead = latestDate.year() - startYear;
int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
yearsAhead -= notThisYear; // latest year which recurred
// Check for the first later date in the current year
if (!notThisYear)
prevDate = getLastDateInYear(latestDate);
if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) {
// Check for a date in the next scheduled year
if (!notThisYear)
yearsAhead -= rFreq;
prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31));
}
break;
}
case rNone:
default:
return QDate();
}
if (prevDate.isValid()) {
// Check that the date found is within the range of the recurrence
if (prevDate < dStart)
return QDate();
if (rDuration >= 0) {
QDate end = endDate();
if (prevDate >= end) {
if (last)
*last = true;
return end;
}
}
}
return prevDate;
}
void Recurrence::setDailySub(short type, int freq, int duration)
{
recurs = type;
rFreq = freq;
rDuration = duration;
rMonthPositions.clear();
rMonthDays.clear();
rYearNums.clear();
if (type != rDaily)
mFloats = false; // sub-daily types can't be floating
if (mParent) mParent->updated();
}
void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration)
{
recurs = type;
if (mCompatVersion < 310 && type == rYearlyDay) {
mCompatRecurs = rYearlyDay;
recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month
feb29type = rMar1; // retain the same day number in the year
}
mFeb29YearlyType = feb29type;
rFreq = freq;
rDuration = duration;
if (type != rYearlyPos)
rMonthPositions.clear();
rMonthDays.clear();
if (mParent) mParent->updated();
}
int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const
{
QDate enddate = endtime.date();
switch (func) {
case END_DATE_AND_COUNT:
if (rDuration < 0) {
endtime = QDateTime();
return 0; // infinite recurrence
}
if (rDuration == 0) {
endtime = rEndDateTime;
func = COUNT_TO_DATE;
}
break;
case COUNT_TO_DATE:
// Count recurrences up to and including the specified date/time.
if (endtime < mRecurStart)
return 0;
if (rDuration == 0 && endtime > rEndDateTime)
enddate = rEndDateTime.date();
else if (!mFloats && mRecurStart.time() > endtime.time())
enddate = enddate.addDays(-1);
break;
case NEXT_AFTER_DATE:
// Find next recurrence AFTER endtime
if (endtime < mRecurStart) {
endtime = mRecurStart;
return 1;
}
if (rDuration == 0 && endtime >= rEndDateTime) {
endtime = QDateTime();
return 0;
}
if (!mFloats && mRecurStart.time() > endtime.time())
enddate = enddate.addDays(-1);
break;
default:
endtime = QDateTime();
return 0;
}
int count = 0; // default = error
bool timed = false;
switch (recurs) {
case rMinutely:
timed = true;
count = secondlyCalc(func, endtime, rFreq*60);
break;
case rHourly:
timed = true;
count = secondlyCalc(func, endtime, rFreq*3600);
break;
case rDaily:
count = dailyCalc(func, enddate);
break;
case rWeekly:
count = weeklyCalc(func, enddate);
break;
case rMonthlyPos:
case rMonthlyDay:
count = monthlyCalc(func, enddate);
break;
case rYearlyMonth:
count = yearlyMonthCalc(func, enddate);
break;
case rYearlyPos:
count = yearlyPosCalc(func, enddate);
break;
case rYearlyDay:
count = yearlyDayCalc(func, enddate);
break;
default:
break;
}
switch (func) {
case END_DATE_AND_COUNT:
case NEXT_AFTER_DATE:
if (count == 0)
endtime = QDateTime();
else if (!timed) {
endtime.setDate(enddate);
endtime.setTime(mRecurStart.time());
}
break;
case COUNT_TO_DATE:
break;
}
return count;
}
int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const
{
QDateTime endtime(enddate, QTime(23,59,59));
switch (func) {
case END_DATE_AND_COUNT:
if (rDuration < 0) {
enddate = QDate();
return 0; // infinite recurrence
}
if (rDuration == 0) {
enddate = rEndDateTime.date();
func = COUNT_TO_DATE;
}
break;
case COUNT_TO_DATE:
// Count recurrences up to and including the specified date.
if (enddate < mRecurStart.date())
return 0;
if (rDuration == 0 && enddate > rEndDateTime.date()) {
enddate = rEndDateTime.date();
endtime.setDate(enddate);
}
break;
case NEXT_AFTER_DATE:
if (enddate < mRecurStart.date()) {
enddate = mRecurStart.date();
return 1;
}
if (rDuration == 0 && enddate >= rEndDateTime.date()) {
enddate = QDate();
return 0;
}
break;
default:
enddate = QDate();
return 0;
}
int count = 0; // default = error
bool timed = false;
switch (recurs) {
case rMinutely:
timed = true;
count = secondlyCalc(func, endtime, rFreq*60);
break;
case rHourly:
timed = true;
count = secondlyCalc(func, endtime, rFreq*3600);
break;
case rDaily:
count = dailyCalc(func, enddate);
break;
case rWeekly:
count = weeklyCalc(func, enddate);
break;
case rMonthlyPos:
case rMonthlyDay:
count = monthlyCalc(func, enddate);
break;
case rYearlyMonth:
count = yearlyMonthCalc(func, enddate);
break;
case rYearlyPos:
count = yearlyPosCalc(func, enddate);
break;
case rYearlyDay:
count = yearlyDayCalc(func, enddate);
break;
default:
@@ -3147,267 +3144,258 @@ bool Recurrence::getYearlyMonthMonths(int day, QValueList<int> &list, QValueList
* specified week which is >= the startDay.
* Parameters: startDay = 1..7 (Monday..Sunday)
* useWeekStart = true to end search at day before next rWeekStart
* = false to search for a full 7 days
* Reply = day of the week (1..7), or 0 if none found.
*/
int Recurrence::getFirstDayInWeek(int startDay, bool useWeekStart) const
{
int last = ((useWeekStart ? rWeekStart : startDay) + 5)%7;
for (int i = startDay - 1; ; i = (i + 1)%7) {
if (rDays.testBit(i))
return i + 1;
if (i == last)
return 0;
}
}
/* From the recurrence day of the week list, get the latest day in the
* specified week which is <= the endDay.
* Parameters: endDay = 1..7 (Monday..Sunday)
* useWeekStart = true to end search at rWeekStart
* = false to search for a full 7 days
* Reply = day of the week (1..7), or 0 if none found.
*/
int Recurrence::getLastDayInWeek(int endDay, bool useWeekStart) const
{
int last = useWeekStart ? rWeekStart - 1 : endDay%7;
for (int i = endDay - 1; ; i = (i + 6)%7) {
if (rDays.testBit(i))
return i + 1;
if (i == last)
return 0;
}
}
/* From the recurrence monthly day number list or monthly day of week/week of
* month list, get the earliest day in the specified month which is >= the
* earliestDate.
*/
QDate Recurrence::getFirstDateInMonth(const QDate &earliestDate) const
{
int earliestDay = earliestDate.day();
int daysInMonth = earliestDate.daysInMonth();
switch (recurs) {
case rMonthlyDay: {
int minday = daysInMonth + 1;
for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) {
int day = *it.current();
if (day < 0)
day = daysInMonth + day + 1;
if (day >= earliestDay && day < minday)
minday = day;
}
if (minday <= daysInMonth)
return earliestDate.addDays(minday - earliestDay);
break;
}
case rMonthlyPos:
case rYearlyPos: {
QDate monthBegin(earliestDate.addDays(1 - earliestDay));
QValueList<int> dayList;
getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek());
for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) {
if (*id >= earliestDay)
return monthBegin.addDays(*id - 1);
}
break;
}
}
return QDate();
}
/* From the recurrence monthly day number list or monthly day of week/week of
* month list, get the latest day in the specified month which is <= the
* latestDate.
*/
QDate Recurrence::getLastDateInMonth(const QDate &latestDate) const
{
int latestDay = latestDate.day();
int daysInMonth = latestDate.daysInMonth();
switch (recurs) {
case rMonthlyDay: {
int maxday = -1;
for (QPtrListIterator<int> it(rMonthDays); it.current(); ++it) {
int day = *it.current();
if (day < 0)
day = daysInMonth + day + 1;
if (day <= latestDay && day > maxday)
maxday = day;
}
if (maxday > 0)
return QDate(latestDate.year(), latestDate.month(), maxday);
break;
}
case rMonthlyPos:
case rYearlyPos: {
QDate monthBegin(latestDate.addDays(1 - latestDay));
QValueList<int> dayList;
getMonthlyPosDays(dayList, daysInMonth, monthBegin.dayOfWeek());
for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) {
if (*id <= latestDay)
return monthBegin.addDays(*id - 1);
}
break;
}
}
return QDate();
}
/* From the recurrence yearly month list or yearly day list, get the earliest
* month or day in the specified year which is >= the earliestDate.
* Note that rYearNums is sorted in numerical order.
*/
QDate Recurrence::getFirstDateInYear(const QDate &earliestDate) const
{
QPtrListIterator<int> it(rYearNums);
switch (recurs) {
case rYearlyMonth: {
int day = recurStart().date().day();
int earliestYear = earliestDate.year();
int earliestMonth = earliestDate.month();
int earliestDay = earliestDate.day();
if (earliestDay > day) {
// The earliest date is later in the month than the recurrence date,
// so skip to the next month before starting to check
if (++earliestMonth > 12)
return QDate();
}
for ( ; it.current(); ++it) {
int month = *it.current();
if (month >= earliestMonth) {
if (day <= 28 || QDate::isValid(earliestYear, month, day))
return QDate(earliestYear, month, day);
if (day == 29 && month == 2) {
// It's a recurrence on February 29th, in a non-leap year
switch (mFeb29YearlyType) {
case rMar1:
return QDate(earliestYear, 3, 1);
case rFeb28:
if (earliestDay <= 28)
return QDate(earliestYear, 2, 28);
break;
case rFeb29:
break;
}
}
}
}
break;
}
case rYearlyPos: {
QValueList<int> dayList;
int earliestYear = earliestDate.year();
int earliestMonth = earliestDate.month();
int earliestDay = earliestDate.day();
for ( ; it.current(); ++it) {
int month = *it.current();
if (month >= earliestMonth) {
QDate monthBegin(earliestYear, month, 1);
getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek());
for (QValueList<int>::ConstIterator id = dayList.begin(); id != dayList.end(); ++id) {
if (*id >= earliestDay)
return monthBegin.addDays(*id - 1);
}
earliestDay = 1;
}
}
break;
}
case rYearlyDay: {
int earliestDay = earliestDate.dayOfYear();
for ( ; it.current(); ++it) {
int day = *it.current();
if (day >= earliestDay && (day <= 365 || day <= earliestDate.daysInYear()))
return earliestDate.addDays(day - earliestDay);
}
break;
}
}
return QDate();
}
/* From the recurrence yearly month list or yearly day list, get the latest
* month or day in the specified year which is <= the latestDate.
* Note that rYearNums is sorted in numerical order.
*/
QDate Recurrence::getLastDateInYear(const QDate &latestDate) const
{
QPtrListIterator<int> it(rYearNums);
switch (recurs) {
case rYearlyMonth: {
int day = recurStart().date().day();
int latestYear = latestDate.year();
int latestMonth = latestDate.month();
if (latestDate.day() > day) {
// The latest date is earlier in the month than the recurrence date,
// so skip to the previous month before starting to check
if (--latestMonth <= 0)
return QDate();
}
for (it.toLast(); it.current(); --it) {
int month = *it.current();
if (month <= latestMonth) {
if (day <= 28 || QDate::isValid(latestYear, month, day))
return QDate(latestYear, month, day);
if (day == 29 && month == 2) {
// It's a recurrence on February 29th, in a non-leap year
switch (mFeb29YearlyType) {
case rMar1:
if (latestMonth >= 3)
return QDate(latestYear, 3, 1);
break;
case rFeb28:
return QDate(latestYear, 2, 28);
case rFeb29:
break;
}
}
}
}
break;
}
case rYearlyPos: {
QValueList<int> dayList;
int latestYear = latestDate.year();
int latestMonth = latestDate.month();
int latestDay = latestDate.day();
for (it.toLast(); it.current(); --it) {
int month = *it.current();
if (month <= latestMonth) {
QDate monthBegin(latestYear, month, 1);
getMonthlyPosDays(dayList, monthBegin.daysInMonth(), monthBegin.dayOfWeek());
for (QValueList<int>::ConstIterator id = dayList.fromLast(); id != dayList.end(); --id) {
if (*id <= latestDay)
return monthBegin.addDays(*id - 1);
}
latestDay = 31;
}
}
break;
}
case rYearlyDay: {
int latestDay = latestDate.dayOfYear();
for (it.toLast(); it.current(); --it) {
int day = *it.current();
if (day <= latestDay)
return latestDate.addDays(day - latestDay);
}
break;
}
}
return QDate();
}
void Recurrence::dump() const
{
- kdDebug() << "Recurrence::dump():" << endl;
-
- kdDebug() << " type: " << recurs << endl;
-
- kdDebug() << " rDays: " << endl;
- int i;
- for( i = 0; i < 7; ++i ) {
- kdDebug() << " " << i << ": "
- << ( rDays.testBit( i ) ? "true" : "false" ) << endl;
- }
+ ;
}