utilsrecurrence.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 1,256 行 · 第 1/3 页

CPP
1,256
字号
    int instance      = -1;
    //int duration    = -1;
    int monthOfYear   = -1;
    wstring pStart, pEnd, startTime, endTime;
    int durationInMinutes = 0; // the duration of the recurrence
    //
    // Get all props from WinRecurrence.
    //
    int i=0;
    winRec.getIntProperty(recurrenceFields[i++],       &recType);
    winRec.getProperty   (recurrenceFields[i++],         pStart);
    winRec.getProperty   (recurrenceFields[i++],           pEnd);
    i++;       // "startTime" is not used, but keep the sequence
    i++;       // "endTime"   is not used, but keep the sequence
    winRec.getIntProperty(recurrenceFields[i++],     &noEndDate);
    winRec.getIntProperty(recurrenceFields[i++],   &occurrences);
    winRec.getIntProperty(recurrenceFields[i++],      &interval);
    winRec.getIntProperty(recurrenceFields[i++], &dayOfWeekMask);
    winRec.getIntProperty(recurrenceFields[i++],    &dayOfMonth);
    winRec.getIntProperty(recurrenceFields[i++],      &instance);
    //winRec.getIntProperty(recurrenceFields[i++],      &duration);
    winRec.getIntProperty(recurrenceFields[i++],   &monthOfYear);

    // The boolean need to take care about the appointment synced from a 7.0.x client
    // against a server 6.5.x that doesn't support the timezone.
    // the data were store with local time
    if (pStart.find(TEXT("Z")) == wstring::npos) {
        toLocal = false;
    }   
    //
    // Recurrence Conversions.
    //
    if (recType<0 || recType>6) {
        // RecurrenceType is mandatory.
        LOG.error("Error setting recurrenceType: %d not supported", recType);
        return incNumProp;
    }
    if (interval < 1) {
        interval = 1;
    }

    // ---- PatternStartDate ----
    if (toLocal) {
        // OLD STYLE (v6.5): get value from Start if not empty. 
        // Used by allday, tasks, and also to keep compatibility on incoming items.
        pStart = start;
    }
    else {
        // Extract pStart (only date) & startTime (only time)
        if (pStart == TEXT("")) {
            // pStart can be missing, for example in vCal 1.0
            pStart = getPatternStartDateFromStart(start, tzInfo);
        }
        replaceAll(L"-", L"", pStart);          // Safe: to accept SIF format "yyyy-mm-dd" too.
        if (pStart.size() >= 15) {
            startTime  = TEXT("18991230T");     // stands for the date = 0
            startTime += pStart.substr(9, 6);
        }
        if (pStart.size() >= 8) {
            pStart     = pStart.substr(0, 8);
            pStart    += TEXT("T000000");
        }
    }

    // ---- PatternEndDate ----
    if (!toLocal) {
        // Extract pEnd (only date)
        if (pEnd.size() >= 8) {
            replaceAll(L"-", L"", pEnd);        // Safe: to accept SIF format "yyyy-mm-dd" too.
            pEnd  = pEnd.substr(0, 8);
            pEnd += TEXT("T000000");
        }
    }
        
    // ---- EndTime ----
    // It's now mandatory, if we set the startTime. We have to calculate it.
    if (startTime.size() > 0) {
        // "Duration" is constant, can be retrieved from (Start - End)
        DATE startDate, endDate, startTimeDate;
        stringTimeToDouble(start,     &startDate);                      // not converting to local time
        stringTimeToDouble(end,       &endDate);
        stringTimeToDouble(startTime, &startTimeDate);

        DATE endTimeDate = startTimeDate + (endDate - startDate);
                                
        // the end time date must be calculated only for the time. The date must be
        // the default one 18991230, so the first part is deleted
        endTimeDate = endTimeDate - (int)endTimeDate; 
                
        WCHAR tmp[20];
        doubleToSystemTimeHourZero(tmp, endTimeDate, FALSE, FALSE);     // not converting to UTC
        endTime = tmp;  

        // calculate the duration of the recurrence: this could be 1,0416666667 that is 25 hours
        // so get the 1, that means 1 day that are 1440 minutes
        DATE val = endDate - startDate;        
        durationInMinutes = (int)val * 1440;  
        // then the 0,41666667 * 1440 that means how many minutes used in a day
        durationInMinutes += round((val - (int)val) * 1440);

    }


    // CHANGE-DAY to Local: modify monthOfYear / dayOfMonth / dayOfWeekMask.
    // All-day event don't need conversions.
    if (toLocal) {
        changeDay(TEXT("Local"), start, &monthOfYear, &dayOfMonth, &dayOfWeekMask);
    }


    //
    // Set all props to MAPI.
    // If using timezone, values should be in local time - however all formats are accepted.
    // NOTE: the order is important!!!
    //
    setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_TYPE, recType);

    FILETIME date = getDatePropertyFromString(pStart, isAllDay);
    setDatePropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_PATTERNSTARTDATE, date);

    if ((noEndDate != 1) && (occurrences <= 0)) {    
        // Set PatternEndDate only if Occurrences not found or wrong.
        if (pEnd.size() > 0) {
            date = getDatePropertyFromString(pEnd);      // Expected UTC value...
            setDatePropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_PATTERNENDDATE, date);
        }
    }

    if (startTime.size() > 0) {
        date = getDatePropertyFromString(startTime, isAllDay);
        setDatePropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_STARTTIME, date);
    }
    /* the end time is not used because the durationInMinutes substitutes this value
    if (endTime.size() > 0) {
        date = getDatePropertyFromString(endTime, isAllDay);
        setDatePropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_ENDTIME, date);
    }
    */
    if (durationInMinutes > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_DURATION, durationInMinutes);        
    }
    if (noEndDate > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_NOEND, noEndDate);
    }
    if ((noEndDate != 1) && (occurrences > 0)) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_OCCURRENCES, occurrences);
    }
    if (interval > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_INTERVAL, interval);
    }
    if (dayOfWeekMask > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_DAYOFWEEKMASK, dayOfWeekMask);
    }
    if (dayOfMonth > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_DAYOFMONTH, dayOfMonth);
    }
    if (instance > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_INSTANCE, instance);
    }    
    if (monthOfYear > 0) {
        setIntPropertyToMapi(&prgPropvalPoom[incNumProp++], PIMPR_RECURRING_MONTHOFYEAR, monthOfYear);
    }

    // Return the updated number of properties.
    return incNumProp;
}



wstring getPatternStartDateFromStart(const wstring& start, const TIME_ZONE_INFORMATION* tzInfo) {

    if (start.find(L"Z", 0) == wstring::npos) {
        // "Start" is in local time, so PatternStart is the same.
        return start;
    }
    if (start.find(L"-", 0) != wstring::npos) {
        // Start is in old SIF style: "yyyy-mm-dd".
        wstring ret = start;
        replaceAll(L"-", L"", ret);
        ret += L"T000000";
        return ret;
    }
    if (start.size() == 8) {
        // Start is in format "yyyymmdd" (allday).
        return start;
    }

    // Backup the current tzInfo of the System
    bool tzBackuped = false;
    TIME_ZONE_INFORMATION backupTzInfo;
    if (tzInfo) {
        GetTimeZoneInformation(&backupTzInfo);
        // Optimization: do it ONLY if tz is different.
        if (!isSameTimezone(tzInfo, &backupTzInfo)) {
            SetTimeZoneInformation(tzInfo);
            tzBackuped = true;
        }
    }

    SYSTEMTIME t;
    DATE startDate = 0;
    WCHAR tmp[20];
    systemTimeToDouble(start.c_str(), &startDate, NULL);      // converts to local time

    VariantTimeToSystemTime(startDate, &t);
    wsprintf(tmp, TEXT("%d%02d%02dT%02d%02d%02d"), t.wYear, t.wMonth, t.wDay,
                                                   t.wHour, t.wMinute, t.wSecond);
    // Restore correct tzInfo.
    if (tzInfo && tzBackuped) {
        SetTimeZoneInformation(&backupTzInfo);
    }

    wstring patternStart = tmp;
    return patternStart;
}





bool changeDay(const wstring& dest, const wstring& start, 
               int* monthOfYear, int* dayOfMonth, int* dayOfWeekMask) 
{

    DATE date = 0;
    SYSTEMTIME time, localTime, utcTime;

    // This call gets 'date' ALWAYS in local time...        *** verify if true on WM! ****  TODO!
    systemTimeToDouble     (start.c_str(), &date, NULL);
    VariantTimeToSystemTime(date,  &time);

    localTime = time;
    localTimeToUTC2(time);
    utcTime   = time;


    // Day to be changed!
    if (localTime.wDay != utcTime.wDay) {
        if (dest == L"Local") {
            time = localTime;
        }

        // MonthOfYear: get from Start
        if (*monthOfYear != 0 && *monthOfYear != -1) {
            *monthOfYear = time.wMonth;
        }

        // DayOfMonth: get from Start
        if (*dayOfMonth != 0 && *dayOfMonth != -1) {
            *dayOfMonth = time.wDay;
        }

        // DayOfWeekMask: shift the mask
        if (*dayOfWeekMask != 0 && *dayOfWeekMask != -1) {
            
            // Calculate if forward or backward 1 day.
            TIME_ZONE_INFORMATION tmz;
            GetTimeZoneInformation(&tmz);
            bool forward;
            if (dest == L"Local") {
                if (tmz.Bias < 0) forward = true;
                else              forward = false;
            }
            else {
                if (tmz.Bias < 0) forward = false;
                else              forward = true;
            }

            // Forward = left shift.
            if (forward) {
                *dayOfWeekMask = *dayOfWeekMask << 1;
                if (*dayOfWeekMask > 127) {
                    *dayOfWeekMask -= 127;
                }
            }
            // Backward = right shift.
            else {
                if (*dayOfWeekMask & 1) {
                    *dayOfWeekMask += 127;
                }
                *dayOfWeekMask = *dayOfWeekMask >> 1;
            }
        }
        return true;
    }
    return false;
}

ArrayList* getRecurrenceProperties(){

    int i = 0;
    ArrayList* props = new ArrayList();

    while (recurrenceFields[i]){
        if (wcscmp (recurrenceFields[i] , L"StartTime") == 0 ||
            wcscmp (recurrenceFields[i] , L"EndTime") == 0 ) {
            i++;    
        }else{
            Property prop;
            char* field = toMultibyte(recurrenceFields[i]);
            prop.setPropName(field);
            props->add(prop);
            delete [] field;
            i++;
        }
    }

    return props;
}


// ************************** TODO: remove? **************************
/*
* delete the occurrences of the recurrence if there are any between them
*/
//void deleteIntraOccurrences(IRecurrencePattern* pRecurrence, DATE originalDate, DATE startDate) {
//
//    IAppointment* pExAppointment;
//
//    if (originalDate > startDate) {
//        for (originalDate-=1; originalDate > startDate; originalDate-=1) {
//
//            pRecurrence->GetOccurrence(originalDate, &pExAppointment);
//            if (pExAppointment) {
//                pExAppointment->Delete();
//                pExAppointment->Release();
//            }
//        }
//    } else {
//        for (originalDate+=1; originalDate < startDate; originalDate+=1) {
//
//            pRecurrence->GetOccurrence(originalDate, &pExAppointment);
//            if (pExAppointment) {
//                pExAppointment->Delete();
//                pExAppointment->Release();
//            }
//        }
//    }
//}

//vector<RecurrenceException> getExceptionList(IRecurrencePattern* pRecurrence,
//                                             const wchar_t* ptrData,
//                                             const wchar_t* action) {
//
//    wchar_t* dummy                  = NULL;
//    wchar_t* dummyEvent             = NULL;
//    wstring  dummyEvent_s;
//    VARIANT_BOOL isNotAllDayEvent   = TRUE;
//    unsigned int pos = 0;
//
//    vector<RecurrenceException> listExceptions;
//
//    unsigned int previous = pos;
//    while ((dummyEvent = getElementContent(&ptrData[pos], (wchar_t*)action, &pos)) != NULL) {
//
//        if (wcscmp(dummyEvent, TEXT("")) == 0) {
//            pos += previous;
//            previous = pos;
//            continue;
//
//        }
//
//        BOOL isAllDayFormat = FALSE;
//        DATE originalDate;
//
//        RecurrenceException rec;
//
//        isAllDayFormat = isDateForAllDayEventFormat(dummyEvent);
//        if (isAllDayFormat) {
//            systemTimeToDoubleBirthFormat(dummyEvent, &originalDate, TEXT("START")); // put 00:00 for the date
//        } else {
//            systemTimeToDouble(dummyEvent, &originalDate, NULL);
//        }
//
//        rec.setOriginalDate(originalDate);
//
//        if (wcscmp(action, EXCLUDE_DATE) == 0) {
//            rec.setIsDeleted(TRUE);
//        } else {
//            rec.setIsDeleted(FALSE);
//            rec.setAllDayEvent(isAllDayFormat);
//        }
//
//        pos += previous;
//        previous = pos;
//
//        listExceptions.push_back(rec);
//    }
//
//    return listExceptions;
//}



/*
* Try to check if exists already an occurrence in that date...
* If exists it delete the existing ont to insert the other appointment exception
*/
//BOOL checkAlreadyAnException(IRecurrencePattern* pRecurrence, DATE originalDate, DATE startDate) {
//
//    IAppointment* pApp;
//    pRecurrence->GetOccurrence(startDate, &pApp);
//
//    if (pApp) {
//
//        if ((int)originalDate - (int)startDate) {
//            LOG.info("An exception of the calendar already exists. Delete it to insert the new one");
//            pApp->Delete();
//            pApp->Release();
//            return TRUE;
//        }
//    }
//
//    return FALSE;
//
//}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?