meetingrequest/mrservices/src/cesmrrecurrenceinfohandler.cpp
branchRCL_3
changeset 25 3533d4323edc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrservices/src/cesmrrecurrenceinfohandler.cpp	Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,1716 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: This file implements CESMRRecurrenceInfoHandler.
+*
+*/
+
+#include "cesmrrecurrenceinfohandler.h"
+#include "cesmrcaluserutil.h"
+#include "esmrdef.h"
+#include "mesmrmeetingrequestentry.h"
+#include "cesmrcaldbmgr.h"
+
+#include <calentry.h>
+#include <calrrule.h>
+#include <ct/rcpointerarray.h>
+#include <calinstanceview.h>
+#include <calinstanceiterator.h>
+
+#include <calinstance.h>
+
+#include "emailtrace.h"
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// Definition for 0
+const TInt KZero = 0;
+
+// Definition for 1
+const TInt KOne = 1;
+
+// Definition for 2
+const TInt KTwo = 2;
+
+// Definition for days in week
+const TInt KDaysInWeek = 7;
+
+// Definition for days in two weeks
+const TInt KDaysInTwoWeeks = 14;
+
+// Definition for montsh in year
+const TInt KMonthsInYear = 12;
+
+/**
+ * Compares two times and returns ETrue if they have same date components
+ * @param aLhs Left hand side component
+ * @param aRhs Right hand side component
+ */
+TBool IsSameDay(
+        const TDateTime& aLhs,
+        const TDateTime& aRhs )
+    {
+    TBool retValue(EFalse);
+
+    if ( aLhs.Day() == aRhs.Day() &&
+         aLhs.Month() == aRhs.Month() &&
+         aLhs.Year() == aRhs.Year()   )
+        {
+        retValue = ETrue;
+        }
+
+    return retValue;
+    }
+
+/**
+ * Checks if instance is included in exception list.
+ * @param aInstanceTime Reference to instance time.
+ * @param aExDateList Reference to exception list.
+ */
+TBool IsTimeIncluded(
+        const TCalTime& aInstanceTime,
+        const RArray<TCalTime>& aExDateList )
+    {
+    FUNC_LOG;
+    TBool included( EFalse );
+    TInt exceptionCount( aExDateList.Count() );
+    if ( exceptionCount )
+        {
+        for (TInt i(0); (i < exceptionCount) && !included ; i++ )
+            {
+            const TCalTime& exceptionTime( aExDateList[i] );
+            TDateTime exDate = exceptionTime.TimeLocalL().DateTime();
+
+            if ( aInstanceTime.TimeLocalL() == exceptionTime.TimeLocalL() )
+                {
+                included = ETrue;
+                }
+            }
+        }
+    return included;
+    }
+
+/**
+ * Calculates time for next instance for recurrent event.
+ * @param aRecurrenceValue Defines the used recurrence.
+ * @param aPrevInstanceStartTime Start time of the previous instance.
+ */
+TTime TimeForNextInstaceStartTime(
+        TESMRRecurrenceValue aRecurrenceValue,
+        TCalTime& aPrevInstanceStartTime )
+    {
+    TTime nextStartTime = aPrevInstanceStartTime.TimeLocalL();
+
+    switch ( aRecurrenceValue )
+        {
+        case ERecurrenceDaily:
+            {
+            nextStartTime += TTimeIntervalDays( KOne );
+            }
+            break;
+        case ERecurrenceWeekly:
+            {
+            nextStartTime += TTimeIntervalDays( KDaysInWeek );
+            }
+            break;
+        case ERecurrenceEverySecondWeek:
+            {
+            nextStartTime += TTimeIntervalDays( KDaysInTwoWeeks );
+            }
+            break;
+        case ERecurrenceMonthly:
+            {
+            nextStartTime += TTimeIntervalMonths( KOne );
+            }
+            break;
+        case ERecurrenceYearly:
+            {
+            nextStartTime += TTimeIntervalYears( KOne );
+            }
+            break;
+        default:
+            {
+            nextStartTime = aPrevInstanceStartTime.TimeLocalL();
+            }
+            break;
+        }
+
+    return nextStartTime;
+    }
+
+
+void CalculateUntilForUnknownRecurrenceL(
+        TTime& aUntil,
+        TCalRRule& aRule )
+    {
+    aUntil = aRule.Until().TimeLocalL();
+    if ( Time::NullTTime() == aUntil )
+        {
+        aUntil = aRule.DtStart().TimeLocalL();
+        TInt factor( aRule.Count() * aRule.Interval() );
+
+        switch ( aRule.Type() )
+            {
+            case TCalRRule::EDaily:
+                {
+                aUntil += TTimeIntervalDays(factor );
+                }
+                break;
+            case TCalRRule::EWeekly:
+                {
+                aUntil += TTimeIntervalDays(factor * KDaysInWeek );
+                }
+                break;
+            case TCalRRule::EMonthly:
+                {
+                aUntil += TTimeIntervalMonths(factor );
+                }
+                break;
+            case TCalRRule::EYearly:
+                {
+                aUntil += TTimeIntervalYears(factor );
+                }
+                break;
+            }
+        }
+    }
+
+/**
+ * Checks if entry's recurrence end time is being adjusted
+ * @param aEntry Reference to entry 
+ */
+TBool RecurrenceEndtimeAdjustedL( 
+        const CCalEntry& aEntry,
+        MESMRCalDbMgr& aCalDb )
+    {
+    TBool retValue( EFalse );
+    
+    TCalRRule rRule;
+    if ( aEntry.GetRRuleL( rRule) )
+        {
+        TCalTime recurrenceId;
+        recurrenceId.SetTimeUtcL( Time::NullTTime() );
+        CCalEntry* entry = aCalDb.FetchEntryL( aEntry.UidL(), recurrenceId  );
+        CleanupStack::PushL( entry );
+        
+        if ( entry )
+            {
+            TCalRRule entryRRule;
+            if ( entry->GetRRuleL( entryRRule ) )
+                {
+                TTime until1 = entryRRule.Until().TimeLocalL();
+                TTime until2 = rRule.Until().TimeLocalL();
+                
+                if ( until1 != until2 )
+                    {
+                    retValue = ETrue;
+                    }
+                }
+            }
+                
+        CleanupStack::PopAndDestroy( entry );        
+        }
+    
+    return retValue;
+    }
+
+/**
+ * Get the beginning of current param time
+ * @param aStartTime Reference to time 
+ */
+TTime BeginningOfDay( const TTime& aStartTime )
+    {
+    TTime zero(TInt64(0));
+    return zero + aStartTime.DaysFrom( zero );
+    }
+
+/**
+ * Get the Time, hour, minute, sec, micsec of current param time
+ * @param aStartTime Reference to time 
+ */
+TTimeIntervalMinutes TimeOfDay( const TTime& aDateTime )
+    {
+    TTime midnight = BeginningOfDay( aDateTime );
+    TTimeIntervalMinutes result;
+    aDateTime.MinutesFrom( midnight, result );
+
+    return result;
+    }
+
+template<typename T> class CleanupResetAndDestroyClose
+    {
+    public:
+        inline static void PushL( T& aRef );
+    private:
+        static void Close( TAny *aPtr );
+    };
+
+template<typename T> inline void CleanupResetAndDestroyClosePushL( T& aRef );
+
+template<typename T> inline void CleanupResetAndDestroyClose<T>::PushL( T& aRef )
+    {
+    CleanupStack::PushL( TCleanupItem( &Close, &aRef ) );
+    }
+
+template<typename T> void CleanupResetAndDestroyClose<T>::Close( TAny *aPtr )
+    {
+    static_cast<T*>(aPtr)->ResetAndDestroy();
+    static_cast<T*>(aPtr)->Close();
+    }
+
+template<typename T> inline void CleanupResetAndDestroyClosePushL( T& aRef )
+    {
+    CleanupResetAndDestroyClose<T>::PushL( aRef );
+    }
+
+}  // namespace
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::CESMRRecurrenceInfoHandler
+// ---------------------------------------------------------------------------
+//
+inline CESMRRecurrenceInfoHandler::CESMRRecurrenceInfoHandler(
+        CCalEntry& aEntry,
+        MESMRCalDbMgr* aCalDb ) :
+        iEntry( aEntry ),
+        iCalDb( aCalDb )
+    {
+    FUNC_LOG;
+    // Not implementation yet
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::~CESMRRecurrenceInfoHandler
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRRecurrenceInfoHandler::~CESMRRecurrenceInfoHandler()
+    {
+    FUNC_LOG;
+    // Not implementation yet
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRRecurrenceInfoHandler* CESMRRecurrenceInfoHandler::NewL(
+        CCalEntry& aEntry )
+    {
+    FUNC_LOG;
+
+    CESMRRecurrenceInfoHandler* self = NewLC( aEntry, NULL );
+    CleanupStack::Pop( self );
+
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRRecurrenceInfoHandler* CESMRRecurrenceInfoHandler::NewL(
+        CCalEntry& aEntry,
+        MESMRCalDbMgr* aCalDb )
+    {
+    FUNC_LOG;
+
+    CESMRRecurrenceInfoHandler* self = NewLC( aEntry, aCalDb );
+    CleanupStack::Pop( self );
+
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::NewLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRRecurrenceInfoHandler* CESMRRecurrenceInfoHandler::NewLC(
+        CCalEntry& aEntry )
+    {
+    FUNC_LOG;
+
+    CESMRRecurrenceInfoHandler* self =
+            new (ELeave) CESMRRecurrenceInfoHandler( aEntry, NULL );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::NewLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRRecurrenceInfoHandler* CESMRRecurrenceInfoHandler::NewLC(
+        CCalEntry& aEntry,
+        MESMRCalDbMgr* aCalDb )
+    {
+    FUNC_LOG;
+
+    CESMRRecurrenceInfoHandler* self =
+            new (ELeave) CESMRRecurrenceInfoHandler( aEntry, aCalDb );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::ConstructL()
+    {
+    FUNC_LOG;
+    // Not implementation yet
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::SetRecurrenceL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::SetRecurrenceL(
+        TESMRRecurrenceValue aRecurrence,
+        TTime aUntil )
+    {
+    FUNC_LOG;
+
+    // Recurrence until time needs to be in Utc mode, because comparison in
+    // NeedToSetRecurrenceL is based on UTC times
+    TCalTime until;
+    until.SetTimeLocalL( aUntil );
+    TTime recUntilUtc = until.TimeUtcL();
+
+    // Check input parameters
+    if ( ERecurrenceNot != aRecurrence &&
+         Time::NullTTime() == aUntil )
+        {
+        // No until parameter set --> Leave
+        User::Leave( KErrArgument );
+        }
+    else if ( ERecurrenceNot == aRecurrence )
+        {
+        // Clear all (recurrence, exceptions) repeating properties
+        iEntry.ClearRepeatingPropertiesL();
+        }
+    else if ( NeedToSetRecurrenceL(aRecurrence, recUntilUtc) )
+        {
+        // Calculate 'correct' until time
+        // Date component is taken from input parameter and
+        // time component from meeting's end time.
+        TDateTime until = aUntil.DateTime();
+        TDateTime endTime = iEntry.EndTimeL().TimeLocalL().DateTime();
+        until.SetHour( endTime.Hour() );
+        until.SetMinute( endTime.Minute() );
+        until.SetSecond( endTime.Second() );
+
+        TCalTime rEndTime;
+        rEndTime.SetTimeLocalL( TTime(until) );
+
+        TCalTime meetingStartTime = iEntry.StartTimeL();
+
+        TCalRRule rRule;
+        rRule.SetDtStart( meetingStartTime );
+
+        // Clear recurrence properties before setting the correct one
+        iEntry.ClearRepeatingPropertiesL();
+
+        switch ( aRecurrence )
+            {
+            case ERecurrenceDaily:
+                {
+                // Set daily recurrence
+                rRule.SetType( TCalRRule::EDaily );
+
+                TTimeIntervalDays daysBetween =
+                    rEndTime.TimeLocalL().DaysFrom(
+                            meetingStartTime.TimeLocalL() );
+
+                // First occurence and days between
+                rRule.SetCount( daysBetween.Int() + KOne);
+                rRule.SetInterval( KOne );
+                }
+                break;
+
+            case ERecurrenceWeekly:
+                {
+                // Set weekly recurrence.
+                rRule.SetType( TCalRRule::EWeekly );
+                TTimeIntervalDays weeksBetween =
+                    rEndTime.TimeLocalL().DaysFrom(
+                            meetingStartTime.TimeLocalL() );
+
+                weeksBetween = weeksBetween.Int() / KDaysInWeek;
+
+                RArray<TDay> dayArray;
+                CleanupClosePushL( dayArray );
+                dayArray.Append( rRule.DtStart().TimeLocalL().DayNoInWeek() );
+                rRule.SetByDay( dayArray );
+                CleanupStack::PopAndDestroy( &dayArray );
+
+                // First occurence and weeks between
+                rRule.SetCount(
+                        weeksBetween.Int() + KOne);
+                rRule.SetInterval( KOne );
+                }
+                break;
+
+            case ERecurrenceEverySecondWeek:
+                {
+                // Set bi-weekly recurrence. This is weekly recurrence
+                // with 2 weeks interval.
+                rRule.SetType( TCalRRule::EWeekly );
+                TTimeIntervalDays fortNightBetween =
+                    rEndTime.TimeLocalL().DaysFrom(
+                            meetingStartTime.TimeLocalL() );
+
+                fortNightBetween =
+                        fortNightBetween.Int() / KDaysInTwoWeeks;
+
+                RArray<TDay> dayArray;
+                CleanupClosePushL( dayArray );
+                dayArray.Append( rRule.DtStart().TimeLocalL().DayNoInWeek() );
+                rRule.SetByDay( dayArray );
+                CleanupStack::PopAndDestroy( &dayArray );
+
+                // First occurence and fortnights between
+                rRule.SetCount(
+                        fortNightBetween.Int() + KOne);
+                rRule.SetInterval( KTwo );
+                }
+                break;
+
+            case ERecurrenceMonthly:
+                {
+                // Set monthly recurrence.
+                rRule.SetType( TCalRRule::EMonthly );
+
+                RArray<TInt> dateArray;
+                CleanupClosePushL( dateArray );
+                dateArray.Append(
+                    rRule.DtStart().TimeLocalL().DayNoInMonth() );
+                rRule.SetByMonthDay( dateArray );
+                CleanupStack::PopAndDestroy( &dateArray );
+
+                TTimeIntervalMonths monthsBetween =
+                    rEndTime.TimeLocalL().MonthsFrom(
+                            meetingStartTime.TimeLocalL() );
+
+                // First occurence and months between
+                rRule.SetCount( monthsBetween.Int() + KOne);
+                rRule.SetInterval( KOne );
+                }
+                break;
+
+            case ERecurrenceYearly:
+                {
+                // Set yearly recurrence.
+                rRule.SetType( TCalRRule::EYearly );
+
+                TTimeIntervalYears yearsBetween =
+                    rEndTime.TimeLocalL().YearsFrom(
+                            meetingStartTime.TimeLocalL() );
+
+                // First occurence and months between
+                rRule.SetCount( yearsBetween.Int() + KOne);
+                rRule.SetInterval( KOne );
+                }
+            default:
+                break;
+            }
+        iEntry.SetRRuleL( rRule );
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::GetRecurrenceL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::GetRecurrenceL(
+        TESMRRecurrenceValue& aRecurrence,
+        TTime& aUntil) const
+    {
+    FUNC_LOG;
+
+    TESMRRecurrenceValue recurrenceValue(ERecurrenceNot);
+
+    // Let's get RDates of the entry also to see if entry is repeating
+    RArray<TCalTime> rdates;
+    CleanupClosePushL( rdates );
+    iEntry.GetRDatesL( rdates );
+
+    TBool hasRdates = rdates.Count() > 0;
+
+    TCalRRule rRule;
+    if ( iEntry.GetRRuleL(rRule) || hasRdates )
+        {
+        // Entry has recurrence
+        recurrenceValue = ERecurrenceUnknown;
+
+        TCalRRule::TType rType = rRule.Type();
+        TInt interval          = rRule.Interval();
+
+        switch ( rType )
+            {
+            case TCalRRule::EInvalid:
+                {
+                // Recurrence type has not yet been defined
+                // --> Consider it then unknown.
+                recurrenceValue = ERecurrenceUnknown;
+                }
+                break;
+
+            case TCalRRule::EDaily:
+                {
+                HandleDailyRecurrenceL( recurrenceValue, rRule );
+                }
+                break;
+
+            case TCalRRule::EWeekly:
+                {
+                HandleWeeklyRecurrenceL( recurrenceValue, rRule );
+                }
+                break;
+
+            case TCalRRule::EMonthly:
+                {
+                HandleMonthlyRecurrenceL( recurrenceValue, rRule );
+                }
+                break;
+
+            case TCalRRule::EYearly:
+                {
+                // Recurrence is based on a number of years
+                if ( KOne == interval)
+                    {
+                    recurrenceValue = ERecurrenceYearly;
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+
+        if ( hasRdates )
+            {
+            // Getting the last RDates occurance time == Until time
+            aUntil = rdates[ rdates.Count() - 1 ].TimeUtcL();
+            }
+        else
+            {
+            CalculateRecurrenceUntilDateL(
+                    recurrenceValue,
+                    aUntil,
+                    rRule,
+                    iEntry );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &rdates );
+    aRecurrence = recurrenceValue;
+    }
+
+
+EXPORT_C void CESMRRecurrenceInfoHandler::RemoveInstanceL(
+        TCalTime aInstanceTime )
+    {
+    FUNC_LOG;
+
+    RArray<TCalTime> exDateList;
+    CleanupClosePushL( exDateList );
+
+    TDateTime instanceException = aInstanceTime.TimeLocalL().DateTime();
+    instanceException.SetHour( KZero );
+    instanceException.SetMinute( KZero );
+    instanceException.SetSecond( KZero );
+    instanceException.SetMicroSecond( KZero );
+
+    TCalTime exceptionTime;
+    exceptionTime.SetTimeUtcL( TTime(instanceException) );
+
+    iEntry.GetExceptionDatesL( exDateList );
+    exDateList.Append( exceptionTime );
+    iEntry.SetExceptionDatesL( exDateList );
+
+    CleanupStack::PopAndDestroy( &exDateList );
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::AddExceptionL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::AddExceptionL(
+        TCalTime aNewInstanceTime,
+         TCalTime aOrginalInstanceTime )
+    {
+    FUNC_LOG;
+
+    // Entry's time has been modified and exception
+    // needs to be added to parent entry
+    RArray<TCalTime> rDateList;
+    CleanupClosePushL( rDateList );
+
+    RArray<TCalTime> exDateList;
+    CleanupClosePushL( exDateList );
+
+    // Only this instance is edited --> Set RRULE to entry
+    iEntry.GetRDatesL( rDateList );
+    iEntry.GetExceptionDatesL( exDateList );
+
+    rDateList.Append( aNewInstanceTime );
+    exDateList.Append( aOrginalInstanceTime );
+
+    iEntry.SetRDatesL( rDateList );
+    iEntry.SetExceptionDatesL( exDateList );
+
+    CleanupStack::PopAndDestroy( &exDateList );
+    CleanupStack::PopAndDestroy( &rDateList );
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::CopyRecurrenceInformationToL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::CopyRecurrenceInformationToL(
+        CCalEntry& aDestination )
+    {
+    FUNC_LOG;
+
+    aDestination.ClearRepeatingPropertiesL();
+
+    TCalRRule rrule;
+    if ( iEntry.GetRRuleL(rrule) )
+        {
+        aDestination.SetRRuleL( rrule );
+
+        RArray<TCalTime> rDateList;
+        CleanupClosePushL( rDateList );
+
+        RArray<TCalTime> exDateList;
+        CleanupClosePushL( exDateList );
+
+        iEntry.GetRDatesL( rDateList );
+        iEntry.GetExceptionDatesL( exDateList );
+
+        aDestination.SetRDatesL( rDateList );
+        aDestination.SetExceptionDatesL( exDateList );
+
+        CleanupStack::PopAndDestroy( &exDateList );
+        CleanupStack::PopAndDestroy( &rDateList );
+        }
+
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::CopyRecurrenceInformationFromL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::CopyRecurrenceInformationFromL(
+        const CCalEntry& aSource )
+    {
+    FUNC_LOG;
+
+    iEntry.ClearRepeatingPropertiesL();
+
+    TCalRRule rrule;
+    if ( aSource.GetRRuleL(rrule) )
+        {
+        iEntry.SetRRuleL( rrule );
+
+        RArray<TCalTime> rDateList;
+        CleanupClosePushL( rDateList );
+
+        RArray<TCalTime> exDateList;
+        CleanupClosePushL( exDateList );
+
+        aSource.GetRDatesL( rDateList );
+        aSource.GetExceptionDatesL( exDateList );
+
+        iEntry.SetRDatesL( rDateList );
+        iEntry.SetExceptionDatesL( exDateList );
+
+        CleanupStack::PopAndDestroy( &exDateList );
+        CleanupStack::PopAndDestroy( &rDateList );
+        }
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::GetFirstInstanceTimeL
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::GetFirstInstanceTimeL(
+        TCalTime& aStart,
+        TCalTime& aEnd )
+    {
+    FUNC_LOG;
+
+    TESMRRecurrenceValue recurrence( ERecurrenceNot );
+    TTime until( Time::NullTTime() );
+    GetRecurrenceL( recurrence, until );
+
+    if ( ERecurrenceNot == recurrence )
+        {
+        aStart = iEntry.StartTimeL();
+        aEnd = iEntry.EndTimeL();
+        }
+    else if ( ERecurrenceUnknown != recurrence )
+        {
+        aStart = iEntry.StartTimeL();
+        aEnd = iEntry.EndTimeL();
+
+        TTimeIntervalMinutes diff;
+        aEnd.TimeLocalL().MinutesFrom(
+                aStart.TimeLocalL(),
+                diff );
+
+        RArray<TCalTime> exDateList;
+        CleanupClosePushL( exDateList );
+        iEntry.GetExceptionDatesL( exDateList );
+
+        TInt exceptionCount( exDateList.Count() );
+        if ( exceptionCount )
+            {
+            TBool timeIncludedInExceptionList(
+                    IsTimeIncluded( aStart, exDateList ) );
+
+            while( timeIncludedInExceptionList )
+                {
+                TTime nextInstanceTime =
+                        TimeForNextInstaceStartTime(
+                                recurrence,
+                                aStart );
+
+                aStart.SetTimeLocalL( nextInstanceTime);
+                timeIncludedInExceptionList =
+                        IsTimeIncluded( aStart, exDateList );
+                }
+            }
+
+        TCalTime untilCalTime;
+        untilCalTime.SetTimeUtcL( until );
+        
+        TDateTime nextTime = aStart.TimeLocalL().DateTime();
+        TDateTime untilTime = untilCalTime.TimeLocalL().DateTime();
+        
+        if ( aStart.TimeUtcL() > untilCalTime.TimeUtcL() )
+            {
+            User::Leave( KErrCorrupt );
+            }
+
+        TTime end = aStart.TimeLocalL() + diff;
+        aEnd.SetTimeLocalL( end );
+
+        CleanupStack::PopAndDestroy( &exDateList );
+        }
+    else
+        {
+        // Unknown recurrence type
+        aStart = iEntry.StartTimeL();
+        aEnd = iEntry.EndTimeL();
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCalenEditorDataHandler::GetPreviousInstanceTimeL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::GetPreviousInstanceTimeL( TCalTime& aPreviousStartTime,
+                                                                    TCalTime& aPreviousEndTime,
+                                                                    TTime aInstanceDateTime )
+    {
+    FUNC_LOG;
+    
+    aPreviousStartTime.SetTimeLocalL( Time::NullTTime() );
+    aPreviousEndTime.SetTimeLocalL( Time::NullTTime() );
+
+    RPointerArray<CCalEntry> entries;
+    CleanupResetAndDestroyClosePushL( entries );
+
+    iCalDb->EntryViewL( iEntry )->FetchL( iEntry.UidL(), entries );
+
+    TCalTime currentInstanceDate = iEntry.RecurrenceIdL();
+    if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
+        {
+        // We must be creating a new exception. Calculate the recurrence id.
+        TTimeIntervalMinutes timeOfDay = TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
+        TTime beginningOfDay = BeginningOfDay( aInstanceDateTime );
+        currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
+        }
+
+    TCalRRule rrule;
+    if( entries[0]->GetRRuleL(rrule) )
+        {
+        TESMRRecurrenceValue repeatIndex = RepeatIndexL( *entries[0] );
+        
+        TBool keepLooking = ETrue;
+        RArray<TCalTime> exdates;
+        CleanupClosePushL( exdates );
+        entries[0]->GetExceptionDatesL(exdates);
+        
+        // Needed for case ERepeatOther
+        TCalRRule::TType type( rrule.Type() );
+        TInt repeatInterval( rrule.Interval() );
+        TCalTime start, end;
+        TTime previousInstanceTime = Time::NullTTime(); 
+        
+        while( keepLooking )
+            {
+            // Subtract the repeat interval of the parent.
+            switch( repeatIndex )
+                {
+                case ERecurrenceDaily:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(1) );
+                    break;
+                    }
+
+                case ERecurrenceWeekly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(7) );
+                    break;
+                    }
+
+                case ERecurrenceEverySecondWeek:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalDays(14) );
+                    break;
+                    }
+
+                case ERecurrenceMonthly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalMonths(1) );
+                    break;
+                    }
+
+                case ERecurrenceYearly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()-TTimeIntervalYears(1) );
+                    break;
+                    }
+
+                case ERecurrenceUnknown:
+                    {
+                    // Check if the current entry being edited is child entry
+                    // If yes, then put back the child entry time to currentInstanceDate  
+                    if( iEntry.RecurrenceIdL().TimeUtcL() != Time::NullTTime() )
+                        {
+                        TTimeIntervalMinutes timeOfDay = TimeOfDay( iEntry.StartTimeL().TimeLocalL() );
+                        TTime beginningOfDay = BeginningOfDay( aInstanceDateTime );
+                        currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
+                        }
+
+                    switch( type )
+                        {
+                        case TCalRRule::EDaily:
+                            {
+                            start.SetTimeLocalL( currentInstanceDate.TimeLocalL() - 
+                                    TTimeIntervalDays( 1 * repeatInterval ) );
+                            break;
+                            }
+
+                        case TCalRRule::EWeekly:
+                            {
+                            start.SetTimeLocalL( currentInstanceDate.TimeLocalL() - 
+                                    TTimeIntervalDays(7 * repeatInterval) );
+                            break;
+                            }
+
+                        case TCalRRule::EMonthly: 
+                            {
+                            // Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
+                            // can go beuong 30 days. Ex: Every third wednesday of every month 
+                            start.SetTimeLocalL( currentInstanceDate.TimeLocalL() -
+                                    TTimeIntervalMonths(repeatInterval)-TTimeIntervalDays(7 * repeatInterval) );
+                            break;
+                            }
+
+                        case TCalRRule::EYearly:  
+                            {
+                            // Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
+                            // can go beuong 365 days. Ex: Every third wednesday of September of every year
+                            start.SetTimeLocalL( currentInstanceDate.TimeLocalL() -
+                                    TTimeIntervalYears(repeatInterval)-TTimeIntervalDays(7 * repeatInterval) );
+                            break;
+                            }
+                        }
+
+                    end.SetTimeLocalL( BeginningOfDay( currentInstanceDate.TimeLocalL() ) );
+                    previousInstanceTime = GetPreviousInstanceForRepeatOtherL( *entries[0], 
+                            CalCommon::TCalTimeRange(start, end) );
+                    currentInstanceDate.SetTimeLocalL( previousInstanceTime );
+                    break;
+                    }
+                    
+                case ERecurrenceNot:
+                default:
+                    {
+                    keepLooking = EFalse;
+                    break;
+                    }
+                }
+
+            // Is currentInstanceDate before parent dt start?
+            if( currentInstanceDate.TimeLocalL() < entries[0]->StartTimeL().TimeLocalL() )
+                {
+                // There are no instances before the exception
+                keepLooking = EFalse;
+                }
+            else
+                {
+                // Is there an exdate on currentInstanceDate?
+                TBool isExdateOnDay = EFalse;
+                for(TInt i=0; i<exdates.Count(); ++i)
+                    {
+                    if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
+                        {
+                        isExdateOnDay = ETrue;
+                        // There is an exdate - is there a child associated with the exdate?
+                        for(TInt j=1; j<entries.Count(); ++j)
+                            {
+                            if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
+                                {
+                                // This child is the previous instance.
+                                aPreviousStartTime = entries[j]->StartTimeL();
+                                aPreviousEndTime = entries[j]->EndTimeL();
+                                keepLooking = EFalse;
+                                }
+                            }
+                        break;
+                        }
+                    }
+
+                if( !isExdateOnDay )
+                    {
+                    // The instance exists and hasn't been deleted or made into an exception.
+                    // Use information from the parent to set the start/end times.
+                    aPreviousStartTime = currentInstanceDate;
+
+                    TTimeIntervalMinutes duration;
+                    TTime start = entries[0]->StartTimeL().TimeLocalL();
+                    TTime end = entries[0]->EndTimeL().TimeLocalL(); 
+                    end.MinutesFrom( start, duration );
+                    aPreviousEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
+                    keepLooking = EFalse;
+                    }
+                }
+            }
+        CleanupStack::PopAndDestroy( &exdates );
+        }
+
+    CleanupStack::PopAndDestroy(&entries);
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::GetNextInstanceTimeL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CESMRRecurrenceInfoHandler::GetNextInstanceTimeL( TCalTime& aNextStartTime,
+                                                                TCalTime& aNextEndTime,
+                                                                TTime aInstanceDateTime )
+    {
+    FUNC_LOG;
+    aNextStartTime.SetTimeLocalL( Time::NullTTime() );
+    aNextEndTime.SetTimeLocalL( Time::NullTTime() );
+
+    RPointerArray<CCalEntry> entries;
+    CleanupResetAndDestroyClosePushL(entries);
+
+    iCalDb->EntryViewL(iEntry)->FetchL( iEntry.UidL(), entries );
+    TCalTime currentInstanceDate = iEntry.RecurrenceIdL();
+    
+    if( currentInstanceDate.TimeUtcL() == Time::NullTTime() )
+        {
+        // We must be creating a new exception. Calculate the recurrence id.
+        TTimeIntervalMinutes timeOfDay = TimeOfDay( entries[0]->StartTimeL().TimeLocalL() );
+        TTime beginningOfDay = BeginningOfDay( aInstanceDateTime );
+        currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
+        }
+
+    TCalRRule rrule;
+    if( entries[0]->GetRRuleL(rrule) )
+        {
+        TESMRRecurrenceValue repeatIndex = RepeatIndexL( *entries[0] );
+        
+        TBool keepLooking = ETrue;
+        RArray<TCalTime> exdates;
+        CleanupClosePushL( exdates );
+        entries[0]->GetExceptionDatesL( exdates );
+        
+        // Needed for case ERepeatOther
+        TCalRRule::TType type( rrule.Type() );
+        TInt repeatInterval( rrule.Interval() );
+        TCalTime start, end;
+        TTime nextInstanceTime = Time::NullTTime(); 
+        
+        while( keepLooking )
+            {
+            // Subtract the repeat interval of the parent.
+            switch( repeatIndex )
+                {
+                case ERecurrenceDaily:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1) );
+                    break;
+                    }
+
+                case ERecurrenceWeekly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(7) );
+                    break;
+                    }
+
+                case ERecurrenceEverySecondWeek:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalDays(14) );
+                    break;
+                    }
+
+                case ERecurrenceMonthly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalMonths(1) );
+                    break;
+                    }
+
+                case ERecurrenceYearly:
+                    {
+                    currentInstanceDate.SetTimeLocalL( currentInstanceDate.TimeLocalL()+TTimeIntervalYears(1) );
+                    break;
+                    }
+
+                case ERecurrenceUnknown:
+                    {
+                    // Check if the current entry being edited is child entry
+                    // If yes, then put back the child entry time to currentInstanceDate
+                    if(iEntry.RecurrenceIdL().TimeUtcL() != Time::NullTTime())
+                        {
+                        TTimeIntervalMinutes timeOfDay = TimeOfDay( iEntry.StartTimeL().TimeLocalL() );
+                        TTime beginningOfDay = BeginningOfDay( aInstanceDateTime );
+                        currentInstanceDate.SetTimeLocalL( beginningOfDay + timeOfDay );
+                        }
+                    
+                    switch( type )
+                        {
+                        case TCalRRule::EDaily:
+                            {
+                            end.SetTimeLocalL( currentInstanceDate.TimeLocalL() + 
+                                    TTimeIntervalDays(1*repeatInterval) );
+                            break;
+                            }
+
+                        case TCalRRule::EWeekly:
+                            {
+                            end.SetTimeLocalL( currentInstanceDate.TimeLocalL() + 
+                                    TTimeIntervalDays(7 *repeatInterval) );
+                            break;
+                            }
+
+                        case TCalRRule::EMonthly:
+                            {
+                            // Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
+                            // can go beuong 30 days. Ex: Every third wednesday of every month
+                            end.SetTimeLocalL( currentInstanceDate.TimeLocalL() + 
+                                    TTimeIntervalMonths(repeatInterval) + TTimeIntervalDays(7 * repeatInterval) );
+                            break;
+                            }
+                            
+                        case TCalRRule::EYearly:
+                            {
+                            // Add 7 days of buffer to cover the cases were gap b/w two instances of the event 
+                            // can go beuong 365 days. Ex: Every third wednesday of September of every year
+                            end.SetTimeLocalL( currentInstanceDate.TimeLocalL() + 
+                                    TTimeIntervalYears(repeatInterval) + TTimeIntervalDays(7 * repeatInterval) );
+                            break;
+                            }
+                        }
+
+                    start.SetTimeLocalL(BeginningOfDay(currentInstanceDate.TimeLocalL()+TTimeIntervalDays(1)));
+                    nextInstanceTime = GetNextInstanceForRepeatOtherL(*entries[0], CalCommon::TCalTimeRange( start, end));
+                    currentInstanceDate.SetTimeLocalL( nextInstanceTime);
+                    break;
+                    }
+                case ERecurrenceNot:
+                    {
+                    keepLooking = EFalse;
+                    break;
+                    }
+
+                default:
+                    {
+                    break;
+                    } 
+                }
+
+            // Is currentInstanceDate after parent dt end?
+            if( currentInstanceDate.TimeLocalL() > rrule.Until().TimeLocalL() )
+                {
+                // There are no instances before the exception
+                keepLooking = EFalse;
+                }
+            else
+                {
+                // Is there an exdate on currentInstanceDate?
+                TBool isExdateOnDay = EFalse;
+                for(TInt i=0; i<exdates.Count(); ++i)
+                    {
+                    if( exdates[i].TimeLocalL() == currentInstanceDate.TimeLocalL() )
+                        {
+                        isExdateOnDay = ETrue;
+                        // There is an exdate - is there a child associated with the exdate?
+                        for(TInt j=1; j<entries.Count(); ++j)
+                            {
+                            if( entries[j]->RecurrenceIdL().TimeLocalL() == currentInstanceDate.TimeLocalL() )
+                                {
+                                // This child is the previous instance.
+                                aNextStartTime = entries[j]->StartTimeL();
+                                aNextEndTime = entries[j]->EndTimeL();
+                                keepLooking = EFalse;
+                                }
+                            }
+                        break;
+                        }
+                    }
+                
+                if( !isExdateOnDay )
+                    {
+                    // The instance exists and hasn't been deleted or made into an exception.
+                    // Use information from the parent to set the start/end times.
+                    aNextStartTime = currentInstanceDate;
+
+                    TTimeIntervalMinutes duration;
+                    TTime start = entries[0]->StartTimeL().TimeLocalL();
+                    TTime end = entries[0]->EndTimeL().TimeLocalL();
+                    end.MinutesFrom( start, duration );
+                    aNextEndTime.SetTimeLocalL( currentInstanceDate.TimeLocalL() + duration );
+                    keepLooking = EFalse;
+                    }
+                }
+            }
+        CleanupStack::PopAndDestroy( &exdates );
+        }
+
+    CleanupStack::PopAndDestroy(&entries);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::GetPreviousInstanceForRepeatOtherL()
+// 
+// -----------------------------------------------------------------------------
+//
+TTime CESMRRecurrenceInfoHandler::GetPreviousInstanceForRepeatOtherL(
+            CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange)
+    {
+    RPointerArray<CCalInstance> allInstances;
+    CleanupResetAndDestroyClosePushL( allInstances );
+    
+    TInt filter;
+    // Get the entry type to be filtered
+    switch(aEntry.EntryTypeL())
+        {
+        case CCalEntry::EAppt:
+            {
+            filter = CalCommon::EIncludeAppts;
+            break;
+            }
+
+        case CCalEntry::ETodo:
+            {
+            filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
+            break;
+            }
+
+        case CCalEntry::EEvent:
+            {
+            filter = CalCommon::EIncludeEvents;
+            break;
+            }
+
+        case CCalEntry::EReminder:
+            {
+            filter = CalCommon::EIncludeReminder;
+            break;
+            }
+
+        case CCalEntry::EAnniv:
+            {
+            filter = CalCommon::EIncludeAnnivs;
+            break;
+            }
+
+        default:
+            {
+            filter = CalCommon::EIncludeAll;
+            break;
+            }
+
+        };
+
+    iCalDb->InstanceViewL(iEntry)->FindInstanceL( allInstances, 
+                                     (CalCommon::TCalViewFilterFlags)filter,
+                                     timeRange);
+
+    TTime previousTime = Time::NullTTime();
+    
+    for( TInt i = allInstances.Count() - 1; i >= 0; i-- )
+        {
+        if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
+            {
+            previousTime = allInstances[i]->Time().TimeLocalL();
+            break;
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &allInstances );  
+    return previousTime;
+    }
+
+// -----------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::GetNextInstanceForRepeatOtherL()
+// 
+// -----------------------------------------------------------------------------
+//
+TTime CESMRRecurrenceInfoHandler::GetNextInstanceForRepeatOtherL( 
+           CCalEntry& aEntry, const CalCommon::TCalTimeRange& timeRange )
+    {
+    RPointerArray<CCalInstance> allInstances;
+    CleanupResetAndDestroyClosePushL( allInstances );
+    
+    TInt filter;
+    // Get the entry type to be filtered
+    switch( aEntry.EntryTypeL() )
+        {
+        case CCalEntry::EAppt:
+            {
+            filter = CalCommon::EIncludeAppts;
+            break;
+            }  
+        case CCalEntry::ETodo:
+            {
+            filter = CalCommon::EIncludeCompletedTodos | CalCommon::EIncludeIncompletedTodos;
+            break;
+            }
+        case CCalEntry::EEvent:
+            {
+            filter = CalCommon::EIncludeEvents;
+            break;
+            }
+        case CCalEntry::EReminder:
+            {
+            filter = CalCommon::EIncludeReminder;
+            break;
+            }
+        case CCalEntry::EAnniv:
+            {
+            filter = CalCommon::EIncludeAnnivs;
+            break;
+            }
+        default:
+            {
+            filter = CalCommon::EIncludeAll;
+            break;
+            }
+        };
+    
+    iCalDb->InstanceViewL(iEntry)->FindInstanceL( allInstances, 
+                                     ( CalCommon::TCalViewFilterFlags )filter,
+                                     timeRange);
+                                     
+    TTime nextTime = Time::NullTTime();
+    
+    TInt i( 0 );
+    for( ; i < allInstances.Count(); i++ )
+        {
+        if( allInstances[i]->Entry().UidL() == aEntry.UidL() )
+            {
+            nextTime = allInstances[i]->Time().TimeLocalL();
+            break;
+            }
+        }
+  
+    CleanupStack::PopAndDestroy( &allInstances );  
+    return nextTime;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::RepeatIndexL
+//
+// ---------------------------------------------------------------------------
+//
+TESMRRecurrenceValue CESMRRecurrenceInfoHandler::RepeatIndexL( const CCalEntry& aEntry )
+    {
+    FUNC_LOG;
+
+    TESMRRecurrenceValue repeatIndex( ERecurrenceNot );
+
+    TCalRRule rrule;
+
+    if( aEntry.GetRRuleL( rrule) )
+        {
+        TCalRRule::TType type( rrule.Type() );
+        TInt repeatInterval( rrule.Interval() );
+
+        // If repeat type of current note is not supported in Calendar,
+        // default repeat value is "Other".
+        repeatIndex = ERecurrenceUnknown;
+
+        switch( type )
+            {
+            case TCalRRule::EDaily:
+                {
+                switch (repeatInterval)
+                    {
+                    case 1:
+                        {
+                        repeatIndex = ERecurrenceDaily;
+                        break;
+                        }
+                    case 7:
+                        {
+                        repeatIndex = ERecurrenceWeekly;
+                        break;
+                        }
+                    case 14:
+                        {
+                        repeatIndex = ERecurrenceEverySecondWeek;
+                        break;
+                        }
+                    default:
+                        {
+                        break;
+                        }
+                    }
+                break;
+                }
+
+            case TCalRRule::EWeekly:
+                {
+                switch( repeatInterval )
+                    {
+                    case 1:
+                        {
+                        repeatIndex = ERecurrenceWeekly;
+                        break;
+                        }
+                    case 2:
+                        {
+                        repeatIndex = ERecurrenceEverySecondWeek;
+                        break;
+                        }
+                    default:
+                        {
+                        break;
+                        }
+                    }
+                break;
+                }
+
+            case TCalRRule::EMonthly:
+                {
+                RArray<TInt> monthDays(31);
+                rrule.GetByMonthDayL ( monthDays );
+
+                if( monthDays.Count() == 1) 
+                    {
+                    switch( repeatInterval )
+                        {
+                        case 1:
+                            {
+                            repeatIndex = ERecurrenceMonthly;
+                            break;
+                            }
+                        // If interval of repeat is 12 months, 
+                        // every year is shown in Note Editor, 
+                        // because it means yearly repeat.
+                        case 12:
+                            {
+                            repeatIndex = ERecurrenceYearly;
+                            break;
+                            }
+                        default:
+                            {
+                            break;
+                            }
+                        }
+                    }
+
+                monthDays.Close();
+                break;
+                }
+                
+            case TCalRRule::EYearly:
+                {
+                if( repeatInterval == 1 )
+                    {
+                    repeatIndex = ERecurrenceYearly;
+                    }
+                break;
+                }
+
+            default:
+                {
+                // If repeat type of current note is not supported in Calendar,
+                // default repeat value is "Other".
+                repeatIndex = ERecurrenceUnknown;
+                break;
+                }
+            }
+        }
+
+    return repeatIndex;
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::CalculateRecurrenceUntilDateL
+//
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::CalculateRecurrenceUntilDateL(
+            TESMRRecurrenceValue aRecurrenceType,
+            TTime& aUntil,
+            TCalRRule& aRule,
+            const CCalEntry& aEntry  ) const
+    {
+    FUNC_LOG;
+    
+    TCalRRule::TType rType = aRule.Type();
+    TInt count             = aRule.Count();
+    TCalTime until         = aRule.Until();
+    
+    if ( count == KZero &&
+         until.TimeUtcL() == Time::NullTTime() )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    if ( !count )
+        {
+        aUntil = until.TimeUtcL();
+        }
+    else
+        {
+        aUntil = aEntry.StartTimeL().TimeUtcL();
+        switch( aRecurrenceType )
+            {
+            case ERecurrenceDaily:
+                {
+                --count;
+                aUntil += TTimeIntervalDays(count);
+                
+                CESMRCalUserUtil* entryUtil = 
+                        CESMRCalUserUtil::NewLC( const_cast<CCalEntry&>(aEntry) );
+                
+                if ( iCalDb && entryUtil->IsAlldayEventL() &&
+                        RecurrenceEndtimeAdjustedL( aEntry, *iCalDb ) )
+                    {
+                    // If until is adjusted for allday entries
+                    // we wound return until day one day too long 
+                    aUntil -= TTimeIntervalDays( KOne );
+                    }                
+                CleanupStack::PopAndDestroy( entryUtil );                
+                break;
+                }
+            case ERecurrenceWeekly:
+                {
+                --count;
+                aUntil += TTimeIntervalDays(count * KDaysInWeek);
+                break;
+                }
+            case ERecurrenceEverySecondWeek:
+                {
+                --count;
+                aUntil += TTimeIntervalDays(count * KDaysInTwoWeeks);
+                break;
+                }
+            case ERecurrenceMonthly:
+                {
+                --count;
+                aUntil += TTimeIntervalMonths(count);
+                break;
+                }
+            case ERecurrenceYearly:
+                {
+                --count;
+                aUntil += TTimeIntervalYears(count);
+                break;
+                }
+            default:
+                {
+                // Check if until date can be calculated
+                CalculateUntilForUnknownRecurrenceL( aUntil, aRule );
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::HandleDailyRecurrenceL
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::HandleDailyRecurrenceL(
+        TESMRRecurrenceValue& aRecurrenceValue,
+        TCalRRule& aRule ) const
+    {
+    FUNC_LOG;
+    TInt interval( aRule.Interval() );
+    aRecurrenceValue = ERecurrenceUnknown;
+
+    // Recurrence is based on a number of days
+    if ( KOne == interval )
+        {
+        // Recurrence occurs daily
+        aRecurrenceValue = ERecurrenceDaily;
+        }
+    else if ( KDaysInWeek ==  interval)
+        {
+        // Interval is seven days
+        // --> recurrence occurs weekly
+        aRecurrenceValue = ERecurrenceWeekly;
+        }
+    else if ( KDaysInTwoWeeks == interval )
+        {
+        // Interval is fortnight -->
+        // recurrence occurs bi-weekly
+        aRecurrenceValue = ERecurrenceEverySecondWeek;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::HandleWeeklyRecurrenceL
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::HandleWeeklyRecurrenceL(
+        TESMRRecurrenceValue& aRecurrenceValue,
+        TCalRRule& aRule ) const
+    {
+    FUNC_LOG;
+    TInt interval( aRule.Interval() );
+
+    RArray<TDay> byDays;
+    CleanupClosePushL( byDays );
+    aRule.GetByDayL(byDays);
+
+    if ( byDays.Count() > KOne )
+        {
+        // Entry is repeated more than once every week or
+        // every second week.
+        aRecurrenceValue = ERecurrenceUnknown;
+        }
+    else if ( KOne == interval)
+        {
+        aRecurrenceValue = ERecurrenceWeekly;
+        }
+    else if ( KTwo == interval )
+        {
+        aRecurrenceValue = ERecurrenceEverySecondWeek;
+        }
+
+    CleanupStack::PopAndDestroy( &byDays );
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::HandleMonthlyRecurrenceL
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::HandleMonthlyRecurrenceL(
+        TESMRRecurrenceValue& aRecurrenceValue,
+        TCalRRule& aRule ) const
+    {
+    FUNC_LOG;
+    TInt interval( aRule.Interval() );
+
+    aRecurrenceValue = ERecurrenceUnknown;
+
+    // Recurrence is based on a number of months
+    // Recurrence is based on a number of weeks
+    if ( KOne == interval)
+        {
+        aRecurrenceValue = ERecurrenceMonthly;
+        }
+    else if ( KMonthsInYear == interval )
+        {
+        aRecurrenceValue = ERecurrenceYearly;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::HandleYearlyRecurrenceL
+// ---------------------------------------------------------------------------
+//
+void CESMRRecurrenceInfoHandler::HandleYearlyRecurrenceL(
+        TESMRRecurrenceValue& aRecurrenceValue,
+        TCalRRule& aRule ) const
+    {
+    FUNC_LOG;
+    TInt interval( aRule.Interval() );
+
+    // Recurrence is based on a number of years
+    if ( KOne == interval)
+        {
+        aRecurrenceValue = ERecurrenceYearly;
+        }
+    else
+        {
+        aRecurrenceValue = ERecurrenceUnknown;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CESMRRecurrenceInfoHandler::NeedToSetRecurrence
+//
+// ---------------------------------------------------------------------------
+//
+TBool CESMRRecurrenceInfoHandler::NeedToSetRecurrenceL(
+        TESMRRecurrenceValue aRecurrence,
+        TTime aUntil ) const
+    {
+    FUNC_LOG;
+    TBool retValue(ETrue);
+
+    TESMRRecurrenceValue oldRecurrence;
+    TTime oldUntil;
+    GetRecurrenceL( oldRecurrence, oldUntil );
+
+    if( oldRecurrence == aRecurrence &&
+        IsSameDay( aUntil.DateTime(), oldUntil.DateTime() )     )
+        {
+        // Recurrence is not changed --> No need to set
+        retValue = EFalse;
+        }
+
+    return retValue;
+    }
+
+// EOF
+