コード例 #1
0
ファイル: recurrence.cpp プロジェクト: pvuorela/kcalcore
void Recurrence::addMonthlyDate( short day )
{
  if ( d->mRecurReadOnly || day > 31 || day < -31 ) {
    return;
  }

  RecurrenceRule *rrule = defaultRRule( true );
  if ( !rrule ) {
    return;
  }

  QList<int> monthDays = rrule->byMonthDays();
  if ( !monthDays.contains( day ) ) {
    monthDays.append( day );
    rrule->setByMonthDays( monthDays );
    updated();
  }
}
コード例 #2
0
ファイル: karecurrence.cpp プロジェクト: serghei/kde3-kdepim
/******************************************************************************
* Return the date/time of the last recurrence.
*/
QDateTime KARecurrence::endDateTime() const
{
    if(mFeb29Type == FEB29_FEB29  ||  duration() <= 1)
    {
        /* Either it doesn't have any special February 29th treatment,
         * it's infinite (count = -1), the end date is specified
         * (count = 0), or it ends on the start date (count = 1).
         * So just use the normal KCal end date calculation.
         */
        return Recurrence::endDateTime();
    }

    /* Create a temporary recurrence rule to find the end date.
     * In a standard KCal recurrence, the 29th February only occurs once every
     * 4 years. So shift the temporary recurrence date to the 28th to ensure
     * that it occurs every year, thus giving the correct occurrence count.
     */
    RecurrenceRule *rrule = new RecurrenceRule();
    rrule->setRecurrenceType(RecurrenceRule::rYearly);
    QDateTime dt = startDateTime();
    QDate d = dt.date();
    switch(d.day())
    {
        case 29:
            // The start date is definitely a recurrence date, so shift
            // start date to the temporary recurrence date of the 28th
            d.setYMD(d.year(), d.month(), 28);
            break;
        case 28:
            if(d.month() != 2  ||  mFeb29Type != FEB29_FEB28  ||  QDate::leapYear(d.year()))
            {
                // Start date is not a recurrence date, so shift it to 27th
                d.setYMD(d.year(), d.month(), 27);
            }
            break;
        case 1:
            if(d.month() == 3  &&  mFeb29Type == FEB29_MAR1  &&  !QDate::leapYear(d.year()))
            {
                // Start date is a March 1st recurrence date, so shift
                // start date to the temporary recurrence date of the 28th
                d.setYMD(d.year(), 2, 28);
            }
            break;
        default:
            break;
    }
    dt.setDate(d);
    rrule->setStartDt(dt);
    rrule->setFloats(doesFloat());
    rrule->setFrequency(frequency());
    rrule->setDuration(duration());
    QValueList<int> ds;
    ds.append(28);
    rrule->setByMonthDays(ds);
    rrule->setByMonths(defaultRRuleConst()->byMonths());
    dt = rrule->endDt();
    delete rrule;

    // We've found the end date for a recurrence on the 28th. Unless that date
    // is a real February 28th recurrence, adjust to the actual recurrence date.
    if(mFeb29Type == FEB29_FEB28  &&  dt.date().month() == 2  &&  !QDate::leapYear(dt.date().year()))
        return dt;
    return dt.addDays(1);
}
コード例 #3
0
ファイル: karecurrence.cpp プロジェクト: serghei/kde3-kdepim
/******************************************************************************
* Must be called after presetting with a KCal::Recurrence, to convert the
* recurrence to KARecurrence types:
* - Convert hourly recurrences to minutely.
* - Remove all but the first day in yearly date recurrences.
* - Check for yearly recurrences falling on February 29th and adjust them as
*   necessary. A 29th of the month rule can be combined with either a 60th day
*   of the year rule or a last day of February rule.
*/
void KARecurrence::fix()
{
    mCachedType = -1;
    mFeb29Type = FEB29_FEB29;
    int convert = 0;
    int days[2] = { 0, 0 };
    RecurrenceRule *rrules[2];
    RecurrenceRule::List rrulelist = rRules();
    RecurrenceRule::List::ConstIterator rr = rrulelist.begin();
    for(int i = 0;  i < 2  &&  rr != rrulelist.end();  ++i, ++rr)
    {
        RecurrenceRule *rrule = *rr;
        rrules[i] = rrule;
        bool stop = true;
        int rtype = recurrenceType(rrule);
        switch(rtype)
        {
            case rHourly:
                // Convert an hourly recurrence to a minutely one
                rrule->setRecurrenceType(RecurrenceRule::rMinutely);
                rrule->setFrequency(rrule->frequency() * 60);
            // fall through to rMinutely
            case rMinutely:
            case rDaily:
            case rWeekly:
            case rMonthlyDay:
            case rMonthlyPos:
            case rYearlyPos:
                if(!convert)
                    ++rr;    // remove all rules except the first
                break;
            case rOther:
                if(dailyType(rrule))
                {
                    // it's a daily rule with BYDAYS
                    if(!convert)
                        ++rr;    // remove all rules except the first
                }
                break;
            case rYearlyDay:
            {
                // Ensure that the yearly day number is 60 (i.e. Feb 29th/Mar 1st)
                if(convert)
                {
                    // This is the second rule.
                    // Ensure that it can be combined with the first one.
                    if(days[0] != 29
                            ||  rrule->frequency() != rrules[0]->frequency()
                            ||  rrule->startDt()   != rrules[0]->startDt())
                        break;
                }
                QValueList<int> ds = rrule->byYearDays();
                if(!ds.isEmpty()  &&  ds.first() == 60)
                {
                    ++convert;    // this rule needs to be converted
                    days[i] = 60;
                    stop = false;
                    break;
                }
                break;     // not day 60, so remove this rule
            }
            case rYearlyMonth:
            {
                QValueList<int> ds = rrule->byMonthDays();
                if(!ds.isEmpty())
                {
                    int day = ds.first();
                    if(convert)
                    {
                        // This is the second rule.
                        // Ensure that it can be combined with the first one.
                        if(day == days[0]  ||  day == -1 && days[0] == 60
                                ||  rrule->frequency() != rrules[0]->frequency()
                                ||  rrule->startDt()   != rrules[0]->startDt())
                            break;
                    }
                    if(ds.count() > 1)
                    {
                        ds.clear();   // remove all but the first day
                        ds.append(day);
                        rrule->setByMonthDays(ds);
                    }
                    if(day == -1)
                    {
                        // Last day of the month - only combine if it's February
                        QValueList<int> months = rrule->byMonths();
                        if(months.count() != 1  ||  months.first() != 2)
                            day = 0;
                    }
                    if(day == 29  ||  day == -1)
                    {
                        ++convert;    // this rule may need to be converted
                        days[i] = day;
                        stop = false;
                        break;
                    }
                }
                if(!convert)
                    ++rr;
                break;
            }
            default:
                break;
        }
        if(stop)
            break;
    }

    // Remove surplus rules
    for(;  rr != rrulelist.end();  ++rr)
    {
        removeRRule(*rr);
        delete *rr;
    }

    QDate end;
    int count;
    QValueList<int> months;
    if(convert == 2)
    {
        // There are two yearly recurrence rules to combine into a February 29th recurrence.
        // Combine the two recurrence rules into a single rYearlyMonth rule falling on Feb 29th.
        // Find the duration of the two RRULEs combined, using the shorter of the two if they differ.
        if(days[0] != 29)
        {
            // Swap the two rules so that the 29th rule is the first
            RecurrenceRule *rr = rrules[0];
            rrules[0] = rrules[1];    // the 29th rule
            rrules[1] = rr;
            int d = days[0];
            days[0] = days[1];
            days[1] = d;        // the non-29th day
        }
        // If February is included in the 29th rule, remove it to avoid duplication
        months = rrules[0]->byMonths();
        if(months.remove(2))
            rrules[0]->setByMonths(months);

        count = combineDurations(rrules[0], rrules[1], end);
        mFeb29Type = (days[1] == 60) ? FEB29_MAR1 : FEB29_FEB28;
    }
    else if(convert == 1  &&  days[0] == 60)
    {
        // There is a single 60th day of the year rule.
        // Convert it to a February 29th recurrence.
        count = duration();
        if(!count)
            end = endDate();
        mFeb29Type = FEB29_MAR1;
    }
    else
        return;

    // Create the new February 29th recurrence
    setNewRecurrenceType(RecurrenceRule::rYearly, frequency());
    RecurrenceRule *rrule = defaultRRule();
    months.append(2);
    rrule->setByMonths(months);
    QValueList<int> ds;
    ds.append(29);
    rrule->setByMonthDays(ds);
    if(count)
        setDuration(count);
    else
        setEndDate(end);
}