pimappservices/calendar/shared/src/agmrptdef.cpp
changeset 0 f979ecb2b13e
child 30 d68a4b5d5885
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "agmrptdef.h"
       
    17 
       
    18 #include "agmsimpleentry.h"
       
    19 #include "agmdate.h"
       
    20 #include "agmutil.h"
       
    21 #include "agmtlsproxy.h"
       
    22 #include "agmdebug.h"
       
    23 #include "agmtzrules.h"
       
    24 
       
    25 #include <vtzrules.h>
       
    26 
       
    27 const TInt16 KRptLocalOffsetNotSet = KMaxTInt16;
       
    28 
       
    29 // --------------------------------------- TAgnRpt -------------------------------
       
    30 
       
    31 TBool TAgnRpt::HourAndMinutesDifferentFromStartTimeL(const TTime& aRptLocalTime) const
       
    32 	{
       
    33 	const TDateTime KRptLocalTestDT = aRptLocalTime.DateTime();
       
    34 	const TDateTime KRptLocalStartDT = StartTimeAsRptLocalL().DateTime();
       
    35 	
       
    36 	if (KRptLocalTestDT.Hour() != KRptLocalStartDT.Hour() ||
       
    37 		KRptLocalTestDT.Minute() != KRptLocalStartDT.Minute())
       
    38 		{
       
    39 		// Hour and minute are not the same, it is possible that they are at the same time in UTC but
       
    40 		// due to the 'missing hour' the two local times appear different.
       
    41 		// Compare the UTC times.
       
    42 		
       
    43 		const TDateTime KUtcStartDT = StartTime().UtcL().DateTime();
       
    44 		const TDateTime KUtcTestDT = ConvertFromRepeatLocalToUtcL(aRptLocalTime).DateTime();
       
    45 		
       
    46 		if (KUtcStartDT.Hour() != KUtcTestDT.Hour() ||
       
    47 			KUtcStartDT.Minute() != KUtcTestDT.Minute())
       
    48 			{
       
    49 			return ETrue;
       
    50 			}
       
    51 		}
       
    52 	return EFalse;
       
    53 	}
       
    54 
       
    55 /** Constructs the repeat object. 
       
    56 The until date is initialised to max time, the repeat interval to 1.
       
    57 @internalComponent
       
    58 */
       
    59 TAgnRpt::TAgnRpt(CAgnRptDef& aOwningRptDef) :
       
    60 	iOwningRptDef(aOwningRptDef)
       
    61 	{
       
    62 	ClearAll();
       
    63 	}
       
    64 
       
    65 /** Constructs a new TAgnRpt object from an existing one.
       
    66 
       
    67 @internalComponent
       
    68 @param aRRule The object to be copied. */
       
    69 TAgnRpt::TAgnRpt(const TAgnRpt& aRRule, CAgnRptDef& aOwningRptDef) :
       
    70 	iOwningRptDef(aOwningRptDef)
       
    71 	{
       
    72 	ClearAll();
       
    73 	iUntilTime = aRRule.iUntilTime;
       
    74 	iInterval = aRRule.iInterval;
       
    75 	iCount = aRRule.iCount;
       
    76 	iUntiltimeHasBeenSet = aRRule.iUntiltimeHasBeenSet;
       
    77 	}
       
    78 	
       
    79 void TAgnRpt::ResetCachedStartTimeOffset()
       
    80 	{
       
    81 	iStartTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
    82 	}
       
    83 
       
    84 void TAgnRpt::ResetCachedUntilTimeOffset()
       
    85 	{
       
    86 	iUntilTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
    87 	}
       
    88 	
       
    89 MAgnCalendarTimeMode::TTimeMode TAgnRpt::TimeMode() const
       
    90 	{
       
    91 	return iOwningRptDef.TimeMode();
       
    92 	}
       
    93 	
       
    94 TTime TAgnRpt::ConvertFromRepeatLocalToUtcL(const TTime& aRptLocalDate) const
       
    95 	{
       
    96 	return iOwningRptDef.ConvertFromRepeatLocalToUtcL(aRptLocalDate);
       
    97 	}
       
    98 	
       
    99 TTime TAgnRpt::ConvertFromUtcToRepeatLocalL(const TTime& aUtcDate) const
       
   100 	{
       
   101 	return iOwningRptDef.ConvertFromUtcToRepeatLocalL(aUtcDate);
       
   102 	}
       
   103 	
       
   104 TTime TAgnRpt::ConvertFromRepeatLocalToSystemLocalL(const TTime& aRptLocalTime) const
       
   105 	{
       
   106 	// If TimeMode is floating, avoid unnecessary conversion by using aRptLocalTime	
       
   107 	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
   108 		{
       
   109 		return aRptLocalTime;
       
   110 		}
       
   111 	
       
   112 	const TTime KUtcTime = ConvertFromRepeatLocalToUtcL(aRptLocalTime);
       
   113 	return AgnDateTime::ConvertToLocalTimeL(KUtcTime);
       
   114 	}
       
   115 
       
   116 TTime TAgnRpt::ConvertFromSystemLocalToRepeatLocalL(const TTime& aSysLocalTime) const
       
   117 	{
       
   118 	// If TimeMode is floating, avoid unnecessary conversion by using aSysLocalTime	
       
   119 	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
   120 		{
       
   121 		return aSysLocalTime;
       
   122 		}
       
   123 	
       
   124 	const TTime KUtcTime = AgnDateTime::ConvertToLocalTimeL(aSysLocalTime);
       
   125 	return ConvertFromUtcToRepeatLocalL(KUtcTime);
       
   126 	}
       
   127 
       
   128 TTime TAgnRpt::StartTimeAsRptLocalL() const
       
   129  	{
       
   130  	TTime startTimeRptLocal;
       
   131  	GetTimeAsRptLocalL(StartTime(), startTimeRptLocal, iStartTimeRptLocalOffset);
       
   132  	return startTimeRptLocal;
       
   133  	}
       
   134 
       
   135 TTime TAgnRpt::UntilTimeAsRptLocalL() const
       
   136  	{
       
   137  	TTime untilTimeRptLocal;
       
   138  	GetTimeAsRptLocalL(UntilTimeL(), untilTimeRptLocal, iUntilTimeRptLocalOffset);
       
   139  	return untilTimeRptLocal;
       
   140  	}
       
   141 
       
   142 void TAgnRpt::GetTimeAsRptLocalL(const TAgnCalendarTime& aCalendarTime, TTime& aTimeAsRptLocal, TInt16& aCachedOffset) const
       
   143 	{
       
   144 	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
   145 		{
       
   146 		aTimeAsRptLocal = aCalendarTime.LocalL(); // if the entry is floating, system local is the same as rpt local
       
   147 		return;
       
   148 		}
       
   149 	
       
   150 	if (aCachedOffset == KRptLocalOffsetNotSet)
       
   151 		{
       
   152 		aCachedOffset = 0;
       
   153  		TTime rptLocalTime = ConvertFromUtcToRepeatLocalL(aCalendarTime.UtcL());
       
   154 		TTimeIntervalMinutes mins;
       
   155 		rptLocalTime.MinutesFrom(aCalendarTime.UtcL(), mins);
       
   156 		aCachedOffset = mins.Int();
       
   157  		}
       
   158 	aTimeAsRptLocal = aCalendarTime.UtcL() + TTimeIntervalMinutes(aCachedOffset);
       
   159  	}
       
   160 
       
   161 EXPORT_C const TAgnCalendarTime& TAgnRpt::UntilTimeL() const
       
   162  	{
       
   163  	//	if iCount is set, the until time will not be set.
       
   164  	if (iCount > 0)
       
   165  		{
       
   166  		TTime time = FindRptUntilTimeLocalL(iCount);
       
   167  			 	
       
   168  		if (!iUntiltimeHasBeenSet)
       
   169  			{
       
   170  			if (TimeMode() == MAgnCalendarTimeMode::EFloating)	
       
   171  				{
       
   172  				iUntilTime.SetFloatingL(time);	
       
   173  				}
       
   174  			else
       
   175  		 		{
       
   176  		 		iUntilTime.SetLocalL(time);	
       
   177  				}
       
   178 			}
       
   179  		}
       
   180  		
       
   181  	if(iUntilTime.UtcL() > AgnDateTime::MaxDate())
       
   182 	 	{
       
   183 	 	iUntilTime.SetUtcL(AgnDateTime::MaxDate());	
       
   184 	 	}
       
   185 	 	
       
   186  	return iUntilTime;
       
   187  	}
       
   188 
       
   189 void TAgnRpt::SetUntilTime(const TAgnCalendarTime& aUntilTime)
       
   190 	{
       
   191 	iUntilTime = aUntilTime;
       
   192 	iUntilTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
   193 	iUntiltimeHasBeenSet = ETrue;
       
   194 	}
       
   195 
       
   196 const TAgnCalendarTime& TAgnRpt::StartTime() const
       
   197 /** Gets the start time as a @see TAgnCalendarTime.
       
   198 
       
   199 @internalComponent
       
   200 @return The start time. */
       
   201 	{
       
   202 	return iOwningRptDef.StartTime();
       
   203 	}
       
   204 
       
   205 void TAgnRpt::ClearAll()
       
   206 /** Clears all the repeat details. 
       
   207 
       
   208 The until time is set to max time and the repeat interval to 1.
       
   209 The cached repeat local time offsets are reset.
       
   210 
       
   211 @internalComponent
       
   212 */
       
   213 	{
       
   214 	iUntilTime.SetUtcL(AgnDateTime::MaxDate()); // this can't leave
       
   215 	iStartTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
   216 	iUntilTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
   217 	iInterval = 1;
       
   218 	iCount = -1;
       
   219 	iUntiltimeHasBeenSet = EFalse;
       
   220 	}
       
   221 
       
   222 
       
   223 TInt TAgnRpt::InvariantL() const
       
   224 /**
       
   225 Check that the rpt doesn't violate its invariants
       
   226 @internalComponent
       
   227 */
       
   228 	{
       
   229 	if (Type() < EDaily || Type() > EYearlyByDay)
       
   230 		{
       
   231 		return (EAgmErrBadRepeat);
       
   232 		}
       
   233 
       
   234  		
       
   235 	if (Interval() <= 0 || !AgnDateTime::IsValidAgendaTTime(iUntilTime.UtcL()) || StartTime() >= iUntilTime)
       
   236 		{
       
   237 		return (EAgmErrBadTime);
       
   238 		}
       
   239 
       
   240 	return (KErrNone);
       
   241 	}
       
   242 
       
   243 
       
   244 
       
   245 void TAgnRpt::InternalizeL(RReadStream& aStream)
       
   246 /** Internalises the repeat definition from a read stream, including type, repeat 
       
   247 details and exception list.
       
   248 
       
   249 @internalComponent
       
   250 @param aStream The stream from which the object should be internalised. */
       
   251 	{
       
   252 	aStream >> iUntilTime;
       
   253 	iInterval = aStream.ReadUint16L();
       
   254 	iStartTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
   255 	iUntilTimeRptLocalOffset = KRptLocalOffsetNotSet;
       
   256 	}
       
   257 
       
   258 
       
   259 void TAgnRpt::ExternalizeL(RWriteStream& aStream) const
       
   260 /** Externalises the repeat definition to a write stream.
       
   261 
       
   262 @internalComponent
       
   263 @param aStream The stream to which the object should be externalised. */
       
   264 	{
       
   265 	aStream << iUntilTime;
       
   266 	aStream.WriteUint16L(iInterval);
       
   267 	}
       
   268 	
       
   269 TBool TAgnRpt::operator==(const TAgnRpt& aRRule) const
       
   270 /** Compares two repeat details objects.
       
   271 
       
   272 @internalComponent
       
   273 @param aRRule The repeat details to compare with this object.
       
   274 @return True if all properties agree, otherwise False. */
       
   275 	{
       
   276 	return (iInterval == aRRule.iInterval && UntilTimeL() == aRRule.UntilTimeL());
       
   277 	}
       
   278 
       
   279 TBool TAgnRpt::operator!=(const TAgnRpt& aRRule) const
       
   280 	{
       
   281 	return ( ! (*this == aRRule) );
       
   282 	}
       
   283 
       
   284 TUint TAgnRpt::MapDayToBits(TDay aDay) const
       
   285 /**
       
   286  Provides a mapping between the enumeration values of TDay to bit fields
       
   287 */
       
   288 	{
       
   289 	switch(aDay)
       
   290 		{
       
   291 	case EMonday : 	return (EBit1);
       
   292 	case ETuesday:	return (EBit2);
       
   293 	case EWednesday:return (EBit3);
       
   294 	case EThursday:	return (EBit4);
       
   295 	case EFriday:	return (EBit5);
       
   296 	case ESaturday:	return (EBit6);
       
   297 	case ESunday:	return (EBit7);
       
   298 	default: 
       
   299 		{
       
   300 		_DBGLOG_ENTRY(AgmDebug::DebugLog("TAgnRpt: Panic - EAgmErrInvalidWeekDay");)
       
   301 		DBG_PANIC(EAgmErrInvalidWeekDay);
       
   302 		}
       
   303 		}
       
   304 	return (EBit0);
       
   305 	}
       
   306 
       
   307 
       
   308 TUint TAgnRpt::MapDateToBits(TUint aNum) const
       
   309 /**
       
   310  Provides a mapping between the numbers 0 to 30 to bit fields.
       
   311  0 = the first day of a month, 30 = the 31st day of the month
       
   312 */
       
   313 	{
       
   314 	if (aNum > 30)
       
   315 		{
       
   316 		_DBGLOG_ENTRY(AgmDebug::DebugLog("TAgnRpt: Panic - EAgmErrInvalidMonthDay");)
       
   317 		DBG_PANIC(EAgmErrInvalidMonthDay);
       
   318 		return (EBit0);
       
   319 		}
       
   320 
       
   321 	return (1 << aNum);
       
   322 	}
       
   323 
       
   324 TTime TAgnRpt::NudgeNextAlignedStartTimeL(const TTime& aRptLocalDate) const
       
   325 	{
       
   326 	TTime startTime = StartTimeAsRptLocalL();
       
   327 
       
   328 	// Find the previous aligned start time from aRptLocalDate
       
   329 	TTime alignedDate(startTime + aRptLocalDate.DaysFrom(startTime));
       
   330 	
       
   331 	const TTime KUtcAlignedDate = ConvertFromRepeatLocalToUtcL(alignedDate);
       
   332 	const TTime KUtcLocalDate = ConvertFromRepeatLocalToUtcL(aRptLocalDate);
       
   333 	
       
   334 	// Don't add a day if aRptLocalDate is already 'aligned start time'
       
   335 	// or if it is before the start of the repeat rule, because DaysFrom
       
   336 	// already returns 'next aligned start time' in that case
       
   337 	if ((aRptLocalDate != alignedDate && aRptLocalDate > startTime) || KUtcLocalDate > KUtcAlignedDate)
       
   338 		{
       
   339 		// Add a day to get the 'next aligned start time'
       
   340 		alignedDate += TTimeIntervalDays(1);
       
   341 		}
       
   342 	
       
   343 	return alignedDate;
       
   344 	}
       
   345  
       
   346 TTime TAgnRpt::NudgePreviousAlignedStartTimeL(const TTime& aRptLocalDate) const
       
   347 	{
       
   348 	TTime startTime = StartTimeAsRptLocalL();
       
   349 	
       
   350 	// Find the previous aligned start time from aRptLocalDate
       
   351 	TTime alignedDate(startTime + aRptLocalDate.DaysFrom(startTime));
       
   352 	
       
   353 	const TTime KUtcAlignedDate = ConvertFromRepeatLocalToUtcL(alignedDate);
       
   354 	const TTime KUtcLocalDate = ConvertFromRepeatLocalToUtcL(aRptLocalDate);
       
   355 
       
   356 	if ( (aRptLocalDate != alignedDate && aRptLocalDate < startTime) || KUtcLocalDate < KUtcAlignedDate )
       
   357 		{
       
   358 		// Subtract a day when aRptLocalDate is before the repeat rule
       
   359 		// start date, because DaysFrom() is a day out in that case 
       
   360 		alignedDate -= TTimeIntervalDays(1);
       
   361 		}
       
   362 		
       
   363 	return alignedDate;
       
   364 	}
       
   365 
       
   366 EXPORT_C TTime TAgnRpt::FindRptUntilTimeLocalL(TUint aCount) const
       
   367 /** Calculates the repeat's end date from the specified number of instances. 
       
   368 
       
   369 If the end date would be after the agenda model's valid date range, it returns 
       
   370 a NULL TTime value.
       
   371 
       
   372 @internalComponent
       
   373 @param aCount The number of instances.
       
   374 @return The end date (System Local Time). */
       
   375 	{
       
   376 	TTime end = FindRptUntilTimeRptLocalL(aCount);
       
   377 	return ConvertFromRepeatLocalToSystemLocalL(end);
       
   378 	}
       
   379 	
       
   380 EXPORT_C TUint16 TAgnRpt::Interval() const
       
   381 /** Gets the repeat interval.
       
   382 
       
   383 @return The interval. */
       
   384 	{
       
   385 	return (iInterval);
       
   386 	}
       
   387 
       
   388 EXPORT_C void TAgnRpt::SetInterval(TUint16 aInterval)
       
   389 /** Sets the repeat interval. 
       
   390 
       
   391 This is a number of days for a daily repeat, a number of weeks for a 
       
   392 weekly repeat, etc. 
       
   393 
       
   394 @param aInterval The interval. */
       
   395 	{
       
   396 	if (aInterval > 0)
       
   397 		{
       
   398 		iInterval = aInterval;
       
   399 		}
       
   400 	}
       
   401 	
       
   402 EXPORT_C void TAgnRpt::SetCount(TInt aRepCount)
       
   403 	{
       
   404 	iCount = aRepCount;
       
   405 	iUntiltimeHasBeenSet = EFalse;
       
   406 	}
       
   407 	
       
   408 EXPORT_C TInt TAgnRpt::Count() const
       
   409 /*
       
   410 >0 - Indicate how many occurrences of a repeating rule.
       
   411  0 - Repeating forever. Note that it is the default value if there is neither Until time nor Count has been set. 
       
   412 <0 - A Until time has been set but not the count. 
       
   413 
       
   414 */	{
       
   415 	return iCount;
       
   416 	}
       
   417 
       
   418 // --------------------------------- TAgnDailyRpt ------------------------------
       
   419 EXPORT_C TAgnDailyRpt::TAgnDailyRpt(CAgnRptDef& aOwningRptDef) : TAgnRpt(aOwningRptDef)
       
   420 /**
       
   421 This is not inline to prevent non-exportable functions causing a linker error in calling code
       
   422 Constructs a default daily repeat object. 
       
   423 @internalComponent
       
   424 */
       
   425 	{
       
   426 	}
       
   427 
       
   428 /** Constructs a new TAgnDailyRpt object from an existing TAgnDailyRpt object.
       
   429 
       
   430 @internalComponent
       
   431 @param aRRule The object to be copied. */
       
   432 EXPORT_C TAgnDailyRpt::TAgnDailyRpt(const TAgnDailyRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
   433 	TAgnRpt(aRRule, aOwningRptDef)
       
   434 	{
       
   435 	}
       
   436 
       
   437 TAgnRpt::TType TAgnDailyRpt::Type() const
       
   438 	{
       
   439 	return TAgnRpt::EDaily;
       
   440 	}
       
   441 
       
   442 TBool TAgnDailyRpt::IsAlignedUtcL(const TTime& aDate) const
       
   443 /**
       
   444  Returns true if aDate (UTC) falls on an instance generated by the repeat algorithm 
       
   445 @internalComponent
       
   446 */
       
   447 	{
       
   448 	// convert aDate from UTC to Repeat Local
       
   449 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
   450 	return IsAlignedRptLocalL(rptLocalDate);
       
   451 	}
       
   452 	
       
   453 TBool TAgnDailyRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
   454 /**
       
   455 Returns true if aDate (Repeat Local) falls on an instance generated by the repeat algorithm 
       
   456 @internalComponent
       
   457 */
       
   458 	{
       
   459 	// see if the day falls on an instance
       
   460 	if ( AgnDateTime::DaysBetweenDates(aDate, StartTimeAsRptLocalL()) % iInterval )
       
   461 		{
       
   462 		return EFalse;
       
   463 		}
       
   464 	
       
   465 	if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
   466 		{
       
   467 		return EFalse;
       
   468 		}
       
   469 	
       
   470 	return ETrue;	
       
   471 	}
       
   472 
       
   473 TUint TAgnDailyRpt::InstanceCountL() const
       
   474 /** Gets the number of instances generated by the repeat algorithm.
       
   475 
       
   476 @internalComponent
       
   477 @return The number of instances. */
       
   478 	{
       
   479 	// to avoid unnecessary time conversions, date substractions should be done in 
       
   480 	// the time reference in which start and end dates are stored
       
   481 	return 1 + (AgnDateTime::DaysBetweenDates(UntilTimeAsRptLocalL(), StartTimeAsRptLocalL()) / iInterval) ;
       
   482 	}
       
   483 
       
   484 TTime TAgnDailyRpt::FindRptUntilTimeRptLocalL(TUint aCount) const
       
   485 	{
       
   486 	// do calculations in repeat local
       
   487 	TUint max = (AgnDateTime::MaxDate().DaysFrom(StartTimeAsRptLocalL()).Int() + 1) / iInterval;
       
   488 	if (aCount > max)
       
   489 		{
       
   490 		return AgnDateTime::MaxDate();
       
   491 		}
       
   492 	return StartTimeAsRptLocalL() + TTimeIntervalDays(iInterval * (aCount-1));
       
   493 	}
       
   494 
       
   495 TTime TAgnDailyRpt::NudgeNextInstanceUtcL(const TTime& aUtcDate) const
       
   496 /**
       
   497 If aUtcDate is already a date generated by the repeat algorithm then that is the date returned,
       
   498 otherwise the next instance from aUtcDate is returned (in UTC time)
       
   499 @internalComponent
       
   500 */
       
   501 	{
       
   502 	//                       aDate-start 
       
   503 	// nextDate = start + ( ------------- + 1) * interval
       
   504 	//                         interval	
       
   505 	// (NOTE: (aDate-start)/interval is NOT incremented if the modulus of division is zero )	
       
   506 
       
   507 	// convert aUtcDate to Repeat Local Time
       
   508 	TTime thisDate = ConvertFromUtcToRepeatLocalL(aUtcDate);
       
   509 		
       
   510 	TTime next = NudgeNextAlignedStartTimeL(thisDate);
       
   511 	
       
   512 	if (IsAlignedRptLocalL(next))
       
   513 		{
       
   514 		return ConvertFromRepeatLocalToUtcL(next);
       
   515 		}
       
   516 		
       
   517 	thisDate = next;
       
   518 	
       
   519 	// get number of last instance
       
   520 	TInt instanceNumber = AgnDateTime::DaysBetweenDates(thisDate, StartTimeAsRptLocalL()) / iInterval;
       
   521 	// if there isn't an instance on our date, we want the next instance
       
   522 	if (AgnDateTime::DaysBetweenDates(thisDate, StartTimeAsRptLocalL()) % iInterval)
       
   523 		{
       
   524 		++instanceNumber;
       
   525 		}
       
   526 	
       
   527 	// resolve instance number to days since start
       
   528 	TInt daysFromStartToNextInstance = instanceNumber * iInterval;
       
   529 	
       
   530 	// add to start date
       
   531 	TTime nextDate = StartTimeAsRptLocalL() + TTimeIntervalDays(daysFromStartToNextInstance);
       
   532 	
       
   533 	if (nextDate > AgnDateTime::MaxDate())
       
   534 		{
       
   535 		return Time::NullTTime();
       
   536 		}
       
   537 		
       
   538 	// convert from repeat local to UTC and return
       
   539 	return ConvertFromRepeatLocalToUtcL(nextDate);
       
   540 	}
       
   541 
       
   542 
       
   543 TTime TAgnDailyRpt::NudgePreviousInstanceUtcL(const TTime& aUtcDate) const
       
   544 /**
       
   545 If aUtcDate is already a date generated by the repeat algorithm then that is the date returned, 
       
   546 otherwise the previous instance is returned.
       
   547 @internalComponent
       
   548 */
       
   549 	{
       
   550 
       
   551 	TTime thisDate = ConvertFromUtcToRepeatLocalL(aUtcDate);	
       
   552 		
       
   553 	TTime prev = NudgePreviousAlignedStartTimeL(thisDate);
       
   554 	
       
   555 	if (IsAlignedRptLocalL(prev))
       
   556 		{
       
   557 		return ConvertFromRepeatLocalToUtcL(prev);
       
   558 		}
       
   559 		
       
   560 	thisDate = prev;
       
   561 	
       
   562 	// get number of last instance
       
   563 	TInt instanceNumber = AgnDateTime::DaysBetweenDates(thisDate, StartTimeAsRptLocalL()) / iInterval;
       
   564 
       
   565 	// resolve instance number to days since start
       
   566 	TInt daysFromStartToPreviousInstance = instanceNumber * iInterval;
       
   567 	
       
   568 	// add to start date
       
   569 	TTime prevDate = StartTimeAsRptLocalL() + TTimeIntervalDays(daysFromStartToPreviousInstance);
       
   570 	
       
   571 	// an instance could have occurred later on our date - get previous instance
       
   572 	if (prevDate > thisDate )
       
   573 		{
       
   574 		prevDate -= TTimeIntervalDays(iInterval);
       
   575 		}
       
   576 	
       
   577 	if (prevDate < AgnDateTime::MinDate())
       
   578 		{
       
   579 		return Time::NullTTime();
       
   580 		}
       
   581 			
       
   582 	return ConvertFromRepeatLocalToUtcL(prevDate);
       
   583 	}
       
   584 
       
   585 
       
   586 // ------------------------------------ TAgnWeeklyRpt--------------------------------
       
   587 EXPORT_C TAgnWeeklyRpt::TAgnWeeklyRpt(CAgnRptDef& aOwningRptDef) : 
       
   588 	TAgnRpt(aOwningRptDef)
       
   589 /** Constructs a weekly repeat object. 
       
   590 
       
   591 The weekly repeat days are all cleared, and the day which is the start of the 
       
   592 week is initialised from the system's locale settings. 
       
   593 
       
   594 @internalComponent
       
   595 */
       
   596 	{
       
   597 	iWeeklyRptDays = 0;
       
   598 	TLocale locale;
       
   599 	SetFirstDayOfWeek(locale.StartOfWeek());
       
   600 	}
       
   601 	
       
   602 EXPORT_C TAgnWeeklyRpt::TAgnWeeklyRpt(const TAgnWeeklyRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
   603 	TAgnRpt(aRRule, aOwningRptDef)
       
   604 /** Constructs a new TAgnWeeklyRpt object from an existing TAgnWeeklyRpt object.
       
   605 
       
   606 @internalComponent
       
   607 @param aRRule The object to be copied. */
       
   608 	{
       
   609 	iWeeklyRptDays = aRRule.iWeeklyRptDays;
       
   610 	iFirstDayOfWeek = aRRule.iFirstDayOfWeek;
       
   611 	}
       
   612 
       
   613 TAgnRpt::TType TAgnWeeklyRpt::Type() const
       
   614 	{
       
   615 	return TAgnRpt::EWeekly;
       
   616 	}
       
   617 
       
   618 EXPORT_C void TAgnWeeklyRpt::SetDay(TDay aDay)
       
   619 /** Adds a day - more than one day can be set at a time.
       
   620 
       
   621 @internalComponent
       
   622 @param aDay The day to be added. */
       
   623 	{ 
       
   624 
       
   625 	iWeeklyRptDays |= MapDayToBits(aDay);
       
   626 	}
       
   627 
       
   628 EXPORT_C TBool TAgnWeeklyRpt::IsDaySet(TDay aDay) const
       
   629 /** Tests whether a specified day has been set.
       
   630 
       
   631 @internalComponent
       
   632 @param aDay The day to test.
       
   633 @return True if the day is set, false if not. */
       
   634 	{ 
       
   635 	return (iWeeklyRptDays & (MapDayToBits(aDay))); 
       
   636 	}
       
   637 
       
   638 
       
   639 EXPORT_C void TAgnWeeklyRpt::SetFirstDayOfWeek(TDay aDay)
       
   640 /**
       
   641 Set the start day of the week
       
   642 
       
   643 @internalComponent
       
   644 */
       
   645 	{
       
   646 	iFirstDayOfWeek= static_cast<TUint8>(MapDayToBits(aDay));
       
   647 	}
       
   648 
       
   649 EXPORT_C TDay TAgnWeeklyRpt::FirstDayOfWeek() const
       
   650 /** Gets the day that is considered to be the first day of the week.
       
   651 
       
   652 This is set during construction from the operating system's locale settings.
       
   653 
       
   654 @internalComponent
       
   655 @return The first day of the week. */
       
   656 	{
       
   657 	switch(iFirstDayOfWeek)
       
   658 		{
       
   659 	case EBit1: return (EMonday);
       
   660 	case EBit2:	return (ETuesday);
       
   661 	case EBit3: return (EWednesday);
       
   662 	case EBit4:	return (EThursday);
       
   663 	case EBit5:	return (EFriday);
       
   664 	case EBit6:	return (ESaturday);
       
   665 	case EBit7:	return (ESunday);
       
   666 	default: 
       
   667 		{
       
   668 		_DBGLOG_ENTRY(AgmDebug::DebugLog("TAgnWeeklyRpt: Panic - EAgmErrInvalidWeekDay");)
       
   669 		DBG_PANIC(EAgmErrInvalidWeekDay);
       
   670 		}
       
   671 		}
       
   672 	return (EMonday); 
       
   673 	}
       
   674 
       
   675 TInt TAgnWeeklyRpt::InvariantL() const
       
   676 /**
       
   677 Check that the rpt doesn't violate its invariants
       
   678 @internalComponent
       
   679 */
       
   680 	{
       
   681 	if (TAgnRpt::InvariantL()==KErrNone && NumDaysSet() > 0  &&
       
   682 		(iFirstDayOfWeek==EBit1|| iFirstDayOfWeek==EBit2 || iFirstDayOfWeek==EBit3|| iFirstDayOfWeek==EBit4 || 
       
   683 		iFirstDayOfWeek==EBit5 || iFirstDayOfWeek==EBit6 || iFirstDayOfWeek==EBit7))
       
   684 		{
       
   685 		return (KErrNone);
       
   686 		}
       
   687 
       
   688 	return (EAgmErrBadRepeat);
       
   689 	}
       
   690 
       
   691 void TAgnWeeklyRpt::InternalizeL(RReadStream& aStream)
       
   692 /** Internalises the weekly repeat object from a read stream.
       
   693 
       
   694 @internalComponent
       
   695 @param aStream Stream from which the object should be internalised. */
       
   696 	{
       
   697 	TAgnRpt::InternalizeL(aStream);
       
   698 	aStream >> iWeeklyRptDays;
       
   699 	aStream >> iFirstDayOfWeek;
       
   700 	}
       
   701 
       
   702 void TAgnWeeklyRpt::ExternalizeL(RWriteStream& aStream) const
       
   703 /** Externalises the weekly repeat object to a write stream.
       
   704 
       
   705 @internalComponent
       
   706 @param aStream Stream to which the object should be externalised. */
       
   707 	{
       
   708 
       
   709 	TAgnRpt::ExternalizeL(aStream);
       
   710 	aStream << iWeeklyRptDays;
       
   711 	aStream << iFirstDayOfWeek;
       
   712 	}
       
   713 
       
   714 TBool TAgnWeeklyRpt::operator==(const TAgnWeeklyRpt& aRRule) const
       
   715 /** Compares two weekly repeat objects for equality.
       
   716 
       
   717 @internalComponent
       
   718 @param aRRule The instance to be compared.
       
   719 @return True if all repeat details are equal, otherwise False. */
       
   720 	{
       
   721 	return (TAgnRpt::operator==(aRRule) && iWeeklyRptDays==aRRule.iWeeklyRptDays);
       
   722 	}
       
   723 
       
   724 TUint TAgnWeeklyRpt::InstanceCountL() const
       
   725 /** Gets the number of instances of the repeat.
       
   726 
       
   727 @internalComponent
       
   728 @return The number of instances. */
       
   729 	{
       
   730 	TTime startOfFirstWeek = DayAtStartOfWeek(StartTimeAsRptLocalL());
       
   731 	TUint count = AgnDateTime::DaysBetweenDates(UntilTimeAsRptLocalL(), startOfFirstWeek) / (7 * iInterval); // No of complete weeks
       
   732 	TTime startDate = startOfFirstWeek + TTimeIntervalDays(count * 7 * iInterval); // must check any remaining bit of last week
       
   733 	count*=NumDaysSet();
       
   734 	while (startDate <= UntilTimeAsRptLocalL())
       
   735 		{
       
   736 		if (IsAlignedRptLocalL(startDate))
       
   737 			{
       
   738 			++count;
       
   739 			}
       
   740 		startDate += TTimeIntervalDays(1);
       
   741 		}
       
   742 
       
   743 	// remove any instances before the start date
       
   744 	while (startOfFirstWeek < StartTimeAsRptLocalL())
       
   745 		{
       
   746 		if (IsAlignedRptLocalL(startOfFirstWeek))
       
   747 			{
       
   748 			count--;
       
   749 			}			
       
   750 		startOfFirstWeek += TTimeIntervalDays(1);
       
   751 		}
       
   752 
       
   753 	return (count);
       
   754 	}
       
   755 	
       
   756 TTime TAgnWeeklyRpt::FindRptUntilTimeRptLocalL(TUint aCount) const
       
   757 	{
       
   758 	const TInt KDaysInAWeek = 7;
       
   759 	
       
   760 	// we do all calculations using repeat local times
       
   761 	TTimeIntervalDays maxDays = AgnDateTime::MaxDate().DaysFrom(StartTimeAsRptLocalL());
       
   762 	TInt max = (((maxDays.Int() / KDaysInAWeek) * NumDaysSet()) / iInterval) + 1;
       
   763 	
       
   764 	if (aCount > max)
       
   765 		{
       
   766 		return AgnDateTime::MaxDate();
       
   767 		}
       
   768 	
       
   769 	TInt instancesPerWeek = NumDaysSet(); // number of instances in each week
       
   770 	TTime end;
       
   771 	if (aCount % instancesPerWeek == 0)
       
   772 		{
       
   773 		end = StartTimeAsRptLocalL() + TTimeIntervalDays(((aCount - 1) / instancesPerWeek) * KDaysInAWeek * iInterval);
       
   774 		}
       
   775 	else
       
   776 		{
       
   777 		end = StartTimeAsRptLocalL() + TTimeIntervalDays((aCount / instancesPerWeek) * KDaysInAWeek * iInterval);
       
   778 		}
       
   779 
       
   780 	if (end > AgnDateTime::MaxDate())
       
   781 		{
       
   782 		return (Time::NullTTime());
       
   783 		}
       
   784 
       
   785 	TInt remainder = aCount % instancesPerWeek;
       
   786 	TInt numToNudge = remainder ? remainder : instancesPerWeek;
       
   787 
       
   788 	end=NudgeNextInstanceRptLocalL(end);
       
   789 	for (; numToNudge > 1 && end != Time::NullTTime(); numToNudge--)
       
   790 		{
       
   791 		end += TTimeIntervalDays(1);
       
   792 		end = NudgeNextInstanceRptLocalL(end);
       
   793 		}	
       
   794 	return end;	
       
   795 	}
       
   796 
       
   797 TTime TAgnWeeklyRpt::NudgeNextInstanceUtcL(const TTime& aDate) const
       
   798 /**
       
   799 If aDate is already a date generated by the repeat algorithm then that is the date returned,
       
   800 otherwise the next instance from aDate is returned (in UTC)
       
   801 */
       
   802 	{
       
   803 	
       
   804 	// Convert aDate from UTC to repeat local
       
   805 	TTime next = ConvertFromUtcToRepeatLocalL(aDate);
       
   806 	
       
   807 	next = NudgeNextInstanceRptLocalL(next);
       
   808 	
       
   809 	// convert from repeat local back to UTC and return
       
   810 	return ConvertFromRepeatLocalToUtcL(next);
       
   811 	}
       
   812 
       
   813 TTime TAgnWeeklyRpt::NudgeNextInstanceRptLocalL(const TTime& aRptLocalDate) const
       
   814 /**
       
   815 Nudges next instance in repeat local time
       
   816 */
       
   817 	{
       
   818 	TTime next = NudgeNextAlignedStartTimeL(aRptLocalDate);
       
   819 	FOREVER
       
   820 		{
       
   821 		if (IsAlignedRptLocalL(next))
       
   822 			{
       
   823 			break;
       
   824 			}
       
   825 		if (next == AgnDateTime::MaxDate())
       
   826 			{
       
   827 			return (Time::NullTTime());
       
   828 			}
       
   829 		next += TTimeIntervalDays(1);
       
   830 		}
       
   831 	return next;
       
   832 	}
       
   833 
       
   834 TTime TAgnWeeklyRpt::NudgePreviousInstanceUtcL(const TTime& aDate) const
       
   835 /**
       
   836 If aDate is already a date generated by the repeat algorithm then that is the date returned, 
       
   837 otherwise the previous instance is returned.
       
   838 
       
   839 The algorithm works by skipping backswards over any unaligned weeks, if the current date 
       
   840 isn't in an aligned week then it is jumped back to take it to the week after the previous aligned 
       
   841 week. Then one day at a time is subtracted and each day checked to see whether it is aligned or not.
       
   842 
       
   843 If no aligned day is found after creeping back 7 days, then the week is re-checked to see if it is 
       
   844 still in an aligned week (by recalling this function). 
       
   845 Both received parameter (aDate) and returned value are expressed in UTC
       
   846 @internalComponent
       
   847 */
       
   848 	{
       
   849 	TTime prev = ConvertFromUtcToRepeatLocalL(aDate);
       
   850 	prev = NudgePreviousInstanceRptLocalL(prev);
       
   851 	return ConvertFromRepeatLocalToUtcL(prev);
       
   852 	}
       
   853 	
       
   854 TTime TAgnWeeklyRpt::NudgePreviousInstanceRptLocalL(const TTime& aDate) const
       
   855 	{
       
   856 	TTime prev = NudgePreviousAlignedStartTimeL(aDate);
       
   857 	
       
   858 	if (IsAlignedRptLocalL(prev))
       
   859 		return prev;
       
   860 	
       
   861 	// get the first day of the week from the prev parameter
       
   862 	TDay dayOfWeekADate = prev.DayNoInWeek();
       
   863 	TTime newDate = prev;
       
   864 	while (dayOfWeekADate != FirstDayOfWeek())
       
   865 		{
       
   866 		newDate -= TTimeIntervalDays(1);
       
   867 		if (dayOfWeekADate > EMonday)
       
   868 			{
       
   869 			dayOfWeekADate = (TDay)(TInt(dayOfWeekADate) - 1);
       
   870 			}
       
   871 		else
       
   872 			{
       
   873 			dayOfWeekADate = ESunday;
       
   874 			}
       
   875 		}
       
   876 	// get the first day of the week from the StartDate
       
   877 	TDay dayOfWeekStartTime = StartTimeAsRptLocalL().DayNoInWeek();
       
   878 	TTime newStartTime = StartTimeAsRptLocalL();
       
   879 	while (dayOfWeekStartTime != FirstDayOfWeek())
       
   880 		{
       
   881 		newStartTime -= TTimeIntervalDays(1);
       
   882 		if (dayOfWeekStartTime > EMonday)
       
   883 			{
       
   884 			dayOfWeekStartTime = (TDay)(TInt(dayOfWeekStartTime) - 1);
       
   885 			}
       
   886 		else
       
   887 			{
       
   888 			dayOfWeekStartTime = ESunday;
       
   889 			}
       
   890 		}
       
   891 	// check if this week has any instances
       
   892 	TInt weeks = AgnDateTime::DaysBetweenDates(newDate, newStartTime) / 7; // needs to compare the first days in the weeks
       
   893 	if (weeks % iInterval != 0)
       
   894 		{
       
   895 		// if not, jump to the week after the previous instance, then creep back one day at a time
       
   896 		TInt daysAfterStartTime = AgnDateTime::DaysBetweenDates(prev, StartTimeAsRptLocalL());
       
   897 		TInt weeksSafelyAfterLastInstance = (daysAfterStartTime/7) % iInterval - 1;
       
   898 		if (weeksSafelyAfterLastInstance > 0)
       
   899 			{
       
   900 			prev = prev - TTimeIntervalDays(weeksSafelyAfterLastInstance*7);
       
   901 			}
       
   902 		}
       
   903 		
       
   904 	TInt count = 0;
       
   905 	while (!IsAlignedRptLocalL(prev) && count < 7)
       
   906 		{
       
   907 		prev -= TTimeIntervalDays(1);
       
   908 		++count;
       
   909 		}
       
   910 	if (count >= 7)
       
   911 		{
       
   912 		prev = NudgePreviousInstanceRptLocalL(prev); // call the 'jump back' code as may no longer be in a week with instances
       
   913 		}
       
   914 	if (prev < AgnDateTime::MinDate())
       
   915 		{
       
   916 		return (Time::NullTTime());
       
   917 		}
       
   918 	if (prev > AgnDateTime::MaxDate())
       
   919 		{
       
   920 		return (Time::NullTTime());
       
   921 		}
       
   922 	return prev;
       
   923 	}
       
   924 
       
   925 
       
   926 TUint TAgnWeeklyRpt::NumDaysSet() const
       
   927 /** Gets the number of repeat days in the week which are set.
       
   928 
       
   929 @internalComponent
       
   930 @return The number of days. */
       
   931 	{
       
   932 
       
   933 	TUint count=0;
       
   934 	for (TUint ii = 1;ii <= 0x40; ii <<= 1)
       
   935 		{
       
   936 		count += !!(iWeeklyRptDays & ii);
       
   937 		}
       
   938 	return (count);
       
   939 	}
       
   940 
       
   941 TBool TAgnWeeklyRpt::IsAlignedUtcL(const TTime& aDate) const
       
   942 /**
       
   943 Returns true if aDate falls on an instance generated by the repeat algorithm
       
   944 (ignores repeat start/end dates)
       
   945 */
       
   946 	{
       
   947 	
       
   948 	TTime localDate = ConvertFromUtcToRepeatLocalL(aDate);
       
   949 	
       
   950 	return IsAlignedRptLocalL(localDate);
       
   951 	}
       
   952 	
       
   953 TBool TAgnWeeklyRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
   954 	{
       
   955 	if (!IsDateInValidWeekRptLocalL(aDate))
       
   956 		return (EFalse);
       
   957 
       
   958 	// if it's in a valid week check if that day is set
       
   959 	if (!IsDaySet(aDate.DayNoInWeek()))
       
   960 		{
       
   961 		return EFalse;
       
   962 		}
       
   963 		
       
   964 	if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
   965 		{
       
   966 		return EFalse;
       
   967 		}
       
   968 	
       
   969 	return ETrue;
       
   970 	}
       
   971 
       
   972 TInt TAgnWeeklyRpt::IsDateInValidWeekRptLocalL(const TTime& aDate) const
       
   973 // aDate is in Repeat Local Time
       
   974 //
       
   975 // Determine if aDate falls in a valid week i.e. one aligned according to the interval.
       
   976 //
       
   977 // For positive weeks the algorithm is its valid if ((week no -1) % interval)==0
       
   978 //		Week numbers: 1  2  3  4  5  6  7  8
       
   979 //   interval of 1    V  V  V  V  V  V  V  V      (5 - 1) % 1  == 0 so valid
       
   980 //   interval of 2    V     V     V     V		  (5 - 1) % 2 == 0 so valid
       
   981 //   interval of 3    V        V        V		  (5 - 1) % 3 == 1 so invalid  etc.
       
   982 //
       
   983 // But for negative weeks the algorithm is its valid if ((week no)% interval)==0
       
   984 // i.e.		
       
   985 //		week no			-4  -3  -2  -1  1  2  3  4  5
       
   986 //  interval of 3            V     		V		 V				(-3 % 3) == 0 so valid
       
   987 //
       
   988 	{
       
   989 		
       
   990 	TInt weekNum=WeekNumRptLocalL(aDate);
       
   991 	if (weekNum > 0) // in a positive week i.e. aDate >= the start of the first week
       
   992 		return ((weekNum-1) % iInterval == 0);
       
   993 	else
       
   994 		return ((weekNum) % iInterval == 0); // aDate < the start of the first week
       
   995 	}
       
   996 
       
   997 
       
   998 TInt TAgnWeeklyRpt::WeekNumRptLocalL(const TTime& aDate) const
       
   999 // First calculate the week number i.e.
       
  1000 //		December    January
       
  1001 //		29  30  31  1  2  3  4  5  6  7  8  9  10
       
  1002 //		T   F   S   S  M  T  W  T  F  S  S  M  T
       
  1003 //                  X
       
  1004 // 		        |     1st week		  | 2nd week
       
  1005 // 
       
  1006 // If X is the start date of the repeat and the first day of the week is a saturday then
       
  1007 // sunday the 8th is in week number  ((8 - (-1)) / 7) + 1  i.e the 2nd week
       
  1008 // Note that -1 represents 31st of december as it is 1 less than whatever the internal 
       
  1009 // representation of 1st Jan is.
       
  1010 
       
  1011 	{
       
  1012 	TTime startOf1stWeek=DayAtStartOfWeek(StartTimeAsRptLocalL());
       
  1013 	TInt weekNo;
       
  1014 		if (aDate >= startOf1stWeek)
       
  1015 			weekNo=(AgnDateTime::DaysBetweenDates(aDate, startOf1stWeek)/7)+1;
       
  1016 		else
       
  1017 			weekNo=((AgnDateTime::DaysBetweenDates(aDate, startOf1stWeek)+1)/7)-1;    // i.e. december the30th above is in week -1
       
  1018 
       
  1019 	return (weekNo);
       
  1020 	}
       
  1021 
       
  1022 
       
  1023 TTime TAgnWeeklyRpt::DayAtStartOfWeek(const TTime& aDay) const
       
  1024 //
       
  1025 // Returns the day at the start of the week containing aDay
       
  1026 //
       
  1027 // i.e. M  T  W  T  F  S  S  M  T  W  T  F  S  S
       
  1028 //      46 47 48 49 50 51 52 53 54 55 56 57 58 59
       
  1029 // If aDay is 53 (Monday) and the start of the week is a monday then 53 is returned
       
  1030 // If aDay is 53 but the start of the week is a Wednesday then 48 is returned
       
  1031     {
       
  1032 
       
  1033     TTime dayAtWeekStart= aDay - TTimeIntervalDays(aDay.DayNoInWeek()) + TTimeIntervalDays(FirstDayOfWeek());
       
  1034     if (dayAtWeekStart < 0)
       
  1035  		dayAtWeekStart = 0;
       
  1036     else if (dayAtWeekStart > aDay)
       
  1037         dayAtWeekStart = dayAtWeekStart - TTimeIntervalDays(7);
       
  1038     return(dayAtWeekStart);
       
  1039     }
       
  1040 
       
  1041 
       
  1042 
       
  1043 
       
  1044 // ------------------------------ TAgnMonthlyRpt ----------------------------  
       
  1045 	
       
  1046 TAgnMonthlyRpt::TAgnMonthlyRpt(CAgnRptDef& aOwningRptDef) : 
       
  1047 	TAgnRpt(aOwningRptDef)
       
  1048 	{
       
  1049 	}
       
  1050 
       
  1051 TAgnMonthlyRpt::TAgnMonthlyRpt(const TAgnRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
  1052 	TAgnRpt(aRRule, aOwningRptDef)
       
  1053 	{
       
  1054 	}
       
  1055 	
       
  1056 TUint TAgnMonthlyRpt::InstanceCountL() const
       
  1057 /** Calculates the number of instances generated by the repeat algorithm.
       
  1058 
       
  1059 @internalComponent
       
  1060 @return The number of instances. */
       
  1061 	{
       
  1062 
       
  1063 	if (NumInstancesPerMonth()==0)
       
  1064 		return (0);
       
  1065 
       
  1066 	TUint count=0;
       
  1067 	TTime nextDate = NudgeNextInstanceRptLocalL(StartTimeAsRptLocalL());
       
  1068 	while (nextDate <= UntilTimeAsRptLocalL() && nextDate >= AgnDateTime::MinDate() && nextDate <= AgnDateTime::MaxDate() )
       
  1069 		{
       
  1070 		nextDate += TTimeIntervalDays(1);
       
  1071 		nextDate = NudgeNextInstanceRptLocalL(nextDate);
       
  1072 		++count;
       
  1073 		}
       
  1074 	return (count);
       
  1075 	}
       
  1076 
       
  1077 TTime TAgnMonthlyRpt::FindRptUntilTimeRptLocalL(TUint aCount) const
       
  1078 	{
       
  1079 	TTimeIntervalMonths monthsFrom = AgnDateTime::MaxDate().MonthsFrom(StartTimeAsRptLocalL());
       
  1080 	TInt numInstancesPerMonth = NumInstancesPerMonth();
       
  1081 	TUint max = (((monthsFrom.Int() + 1) * numInstancesPerMonth) / iInterval) + 1;
       
  1082 	
       
  1083 	if (aCount > max)
       
  1084 		{
       
  1085 		return AgnDateTime::MaxDate();
       
  1086 		}
       
  1087 	TInt rem = aCount;
       
  1088 	
       
  1089 	TTime end=StartTimeAsRptLocalL();
       
  1090 	if (IsAlignedRptLocalL(end))
       
  1091 		rem--;
       
  1092 	while (rem)
       
  1093 		{
       
  1094 		end += TTimeIntervalDays(1);
       
  1095 		if (end > AgnDateTime::MaxDate())
       
  1096 			return (Time::NullTTime());
       
  1097 		end=NudgeNextInstanceRptLocalL(end);
       
  1098 		rem--;
       
  1099 		}
       
  1100 	return end;
       
  1101 	}
       
  1102 	
       
  1103 TBool TAgnMonthlyRpt::DateFallsInAlignedMonthL(const TDateTime& aDate) const
       
  1104 /**
       
  1105 Returns ETrue if aDate (Repeat Local Time) falls within a month generated by the the repeat algorithm for
       
  1106 the monthly repeat types.
       
  1107 @internalComponent
       
  1108 */
       
  1109 	{
       
  1110 
       
  1111 	TDateTime start = StartTimeAsRptLocalL().DateTime();
       
  1112 	if (((aDate.Month() + (12 * aDate.Year())) -
       
  1113 			(start.Month() + (12 * start.Year()))) % iInterval)
       
  1114 		{
       
  1115 		return (EFalse);
       
  1116 		}
       
  1117 	return (ETrue);
       
  1118 	}
       
  1119 
       
  1120 
       
  1121 void TAgnMonthlyRpt::NudgeNextMonthL(TTime& aDate) const
       
  1122 /**
       
  1123 Finds start of next valid month; doesnt change day if it is in valid month
       
  1124 In this case you dont want to risk returning a result prior to aDate 
       
  1125 @internalComponent
       
  1126 */
       
  1127 	{
       
  1128 
       
  1129 	TDateTime next = aDate.DateTime();
       
  1130 	TDateTime start = StartTimeAsRptLocalL().DateTime();
       
  1131 
       
  1132 	TTimeIntervalMonths monthsSince = (next.Month() - start.Month()) + 12 * (next.Year() - start.Year()); // no months since repeat started
       
  1133 	TTimeIntervalMonths nextValidMonth = ((monthsSince.Int()+Interval()-1)/Interval())*Interval();
       
  1134 	if (nextValidMonth > monthsSince)
       
  1135 		{
       
  1136 		AgnDateTime::AddTo(next,TTimeIntervalMonths(nextValidMonth.Int() - monthsSince.Int()));
       
  1137 		next.SetDay(0);		// set to start of month
       
  1138 		aDate = TTime(next);
       
  1139 		if (aDate > AgnDateTime::MaxDate())
       
  1140 			aDate = Time::NullTTime();
       
  1141 		}
       
  1142 	}
       
  1143 
       
  1144 void TAgnMonthlyRpt::NudgePreviousMonthL(TTime& aDate) const
       
  1145 /**
       
  1146 Finds previous valid month; doesnt change day if it is in valid month
       
  1147 In this case you dont want to risk returning a result after aDate
       
  1148 @internalComponent
       
  1149 */
       
  1150 	{
       
  1151 	TDateTime prev = aDate.DateTime();
       
  1152 	TDateTime start = StartTimeAsRptLocalL().DateTime();
       
  1153 	TTimeIntervalMonths monthNo=prev.Month() - start.Month() + 12 * (prev.Year() - start.Year());
       
  1154 	TTimeIntervalMonths monthsSince=(monthNo.Int()/Interval())*Interval();
       
  1155 	
       
  1156 	if (monthsSince.Int() < Abs(monthNo.Int()) || Abs(monthNo.Int() - monthsSince.Int()) == 11)
       
  1157 		{
       
  1158 		AgnDateTime::AddTo(prev,TTimeIntervalMonths(monthsSince.Int()-monthNo.Int()));
       
  1159 		prev.SetDay(Time::DaysInMonth(prev.Year(),prev.Month())-1);	// move to end of month
       
  1160 		aDate = TTime(prev);
       
  1161 		if (aDate < AgnDateTime::MinDate())
       
  1162 			aDate=Time::NullTTime();
       
  1163 		}
       
  1164 	}
       
  1165 
       
  1166 TTime TAgnMonthlyRpt::NudgeNextInstanceUtcL(const TTime& aDate) const
       
  1167 /**
       
  1168 If aDate is already a date generated by the repeat algorithm then that is the date returned,
       
  1169 otherwise the next instance from aDate is returned 
       
  1170 @internalComponent
       
  1171 */
       
  1172 	{
       
  1173 	TTime next = ConvertFromUtcToRepeatLocalL(aDate);
       
  1174 	next = NudgeNextInstanceRptLocalL(next);
       
  1175 	return ConvertFromRepeatLocalToUtcL(next);
       
  1176 	}
       
  1177 
       
  1178 TTime TAgnMonthlyRpt::NudgeNextInstanceRptLocalL(const TTime& aDate) const
       
  1179 /**
       
  1180 If aDate is already a date generated by the repeat algorithm then that is the date returned,
       
  1181 otherwise the next instance from aDate is returned
       
  1182 @internalComponent
       
  1183 */
       
  1184 	{
       
  1185 
       
  1186 	TTime next = NudgeNextAlignedStartTimeL(aDate);
       
  1187 	
       
  1188 	if ( ! DateFallsInAlignedMonthL(next.DateTime()) || ! IsAlignedRptLocalL(next))
       
  1189 		{
       
  1190 		NudgeNextMonthL(next);
       
  1191 		if (next == Time::NullTTime())
       
  1192 			{
       
  1193 			return (Time::NullTTime());
       
  1194 			}
       
  1195 		while ( ! IsAlignedRptLocalL(next) )
       
  1196 			{ 
       
  1197 			TTimeIntervalDays numDaysToNextInstance = NumDaysToNextInstanceFrom(next);
       
  1198 			if (numDaysToNextInstance.Int())
       
  1199 				{
       
  1200 				next = next + TTimeIntervalDays(numDaysToNextInstance.Int());
       
  1201 				}
       
  1202 			else
       
  1203 				// jump to the 1st day of the next month
       
  1204 				{
       
  1205 				TDateTime d1 = next.DateTime();
       
  1206 				TInt day = d1.Day();
       
  1207 				TInt daysInMonth = Time::DaysInMonth(d1.Year(),d1.Month());
       
  1208 				next = next + TTimeIntervalDays(daysInMonth - day);
       
  1209 				}
       
  1210 			TDateTime d2 = next.DateTime();
       
  1211 			if (d2.Day() == 0)	// i.e. the 1st of the month
       
  1212 				{
       
  1213 				AgnDateTime::AddTo(d2,TTimeIntervalMonths(Interval()-1));
       
  1214 				next = TTime(d2);
       
  1215 				}
       
  1216 			if (next > AgnDateTime::MaxDate())
       
  1217 				{
       
  1218 				return (Time::NullTTime());
       
  1219 				}
       
  1220 			}
       
  1221 		}
       
  1222 	return next;
       
  1223 	}	
       
  1224 
       
  1225 TTime TAgnMonthlyRpt::NudgePreviousInstanceUtcL(const TTime& aDate) const
       
  1226 //
       
  1227 // If aDate is already a date generated by the repeat algorithm then that is the date returned, 
       
  1228 // otherwise the previous instance is returned (UTC)
       
  1229 //
       
  1230 	{
       
  1231 	TTime prev = ConvertFromUtcToRepeatLocalL(aDate);
       
  1232 	prev = NudgePreviousInstanceRptLocalL(prev);
       
  1233 	return ConvertFromRepeatLocalToUtcL(prev);
       
  1234 	}
       
  1235 
       
  1236 TTime TAgnMonthlyRpt::NudgePreviousInstanceRptLocalL(const TTime& aDate) const
       
  1237 //
       
  1238 // If aDate is already a date generated by the repeat algorithm then that is the date returned, 
       
  1239 // otherwise the previous instance is returned (Repeat Local Time)
       
  1240 //
       
  1241 	{
       
  1242 	TTime prev = NudgePreviousAlignedStartTimeL(aDate);
       
  1243 	if (!(IsAlignedRptLocalL(prev)))
       
  1244 		{
       
  1245 		if (Interval() > 1)
       
  1246 			{
       
  1247 			NudgePreviousMonthL(prev);
       
  1248 			if (prev==Time::NullTTime())
       
  1249 				return (Time::NullTTime());
       
  1250 			if (IsAlignedRptLocalL(prev))
       
  1251 				return prev;
       
  1252 			}
       
  1253 		do
       
  1254 			{
       
  1255 			TDateTime prevTDateTime=prev.DateTime();
       
  1256 			if (prevTDateTime.Day()==0 && Interval() > 1)
       
  1257 				{
       
  1258 				AgnDateTime::AddTo(prevTDateTime,TTimeIntervalMonths(1-Interval()));
       
  1259 				prev = TTime(prevTDateTime);
       
  1260 				}
       
  1261 			if (prev == AgnDateTime::MinDate())		
       
  1262 				return (Time::NullTTime());
       
  1263 			prev -= TTimeIntervalDays(1);
       
  1264 			}
       
  1265 		while (!(IsAlignedRptLocalL(prev)));
       
  1266 		}
       
  1267 	return (prev);
       
  1268 	}
       
  1269 
       
  1270 
       
  1271 // ------------------------------------- TAgnMonthlyByDaysRpt -------------------------
       
  1272 EXPORT_C TAgnMonthlyByDaysRpt::TAgnMonthlyByDaysRpt(CAgnRptDef& aOwningRptDef) : 
       
  1273 	TAgnMonthlyRpt(aOwningRptDef)
       
  1274 /** Constructs a monthly by days repeat object. 
       
  1275 
       
  1276 The repeat days are all cleared. 
       
  1277 
       
  1278 @internalComponent
       
  1279 */
       
  1280 	{
       
  1281 	ClearAllDays();
       
  1282 	}
       
  1283 	
       
  1284 EXPORT_C TAgnMonthlyByDaysRpt::TAgnMonthlyByDaysRpt(const TAgnMonthlyByDaysRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
  1285 	TAgnMonthlyRpt(aRRule, aOwningRptDef)
       
  1286 /** Constructs a new TAgnMonthlyByDaysRpt object from an existing one.
       
  1287 
       
  1288 @internalComponent
       
  1289 @param aRRule The object to be copied. */
       
  1290 	{
       
  1291 	for (TInt i = 0; i < KMonthlyByDaysArraySize; ++i)
       
  1292 		{
       
  1293 		iMonthlyRptDays[i] = aRRule.iMonthlyRptDays[i];
       
  1294 		}
       
  1295 	}
       
  1296 
       
  1297 TAgnRpt::TType TAgnMonthlyByDaysRpt::Type() const
       
  1298 	{
       
  1299 	return TAgnRpt::EMonthlyByDays;
       
  1300 	}
       
  1301 	
       
  1302 void TAgnMonthlyByDaysRpt::ClearAllDays()
       
  1303 /** Clears all the monthly repeat days. 
       
  1304 
       
  1305 @internalComponent
       
  1306 */
       
  1307 	{
       
  1308 
       
  1309 	iMonthlyRptDays[EFirst]=0;
       
  1310 	iMonthlyRptDays[ESecond]=0;
       
  1311 	iMonthlyRptDays[EThird]=0;
       
  1312 	iMonthlyRptDays[EFourth]=0;
       
  1313 	iMonthlyRptDays[ELast]=0;
       
  1314 	}
       
  1315 
       
  1316 EXPORT_C void TAgnMonthlyByDaysRpt::SetDay(TDay aDay,TWeekInMonth aWeek)
       
  1317 /** Adds a day in the specified week to the repeat object.
       
  1318 
       
  1319 @internalComponent
       
  1320 @param aDay The day to be added.
       
  1321 @param aWeek The week in the month for the day to be added. */
       
  1322 	{
       
  1323 
       
  1324 	__ASSERT_DEBUG(aWeek == EFirst || aWeek == ESecond || aWeek == EThird || aWeek == EFourth || aWeek == ELast,
       
  1325 				Panic(EAgmErrInvalidWeekNumber));
       
  1326 
       
  1327 	iMonthlyRptDays[aWeek] |= MapDayToBits(aDay);
       
  1328 	}
       
  1329 
       
  1330 
       
  1331 EXPORT_C TBool TAgnMonthlyByDaysRpt::IsDaySet(TDay aDay,TWeekInMonth aWeek) const
       
  1332 /** Tests whether a day is set as a repeat in the given week.
       
  1333 
       
  1334 @internalComponent
       
  1335 @param aDay The day to be tested for.
       
  1336 @param aWeek The week in the month.
       
  1337 @return True if set, False if not set. */
       
  1338 	{
       
  1339 
       
  1340 	__ASSERT_DEBUG(aWeek == EFirst || aWeek == ESecond || aWeek == EThird || aWeek == EFourth || aWeek == ELast,
       
  1341 				Panic(EAgmErrInvalidWeekNumber));
       
  1342 
       
  1343 	return (iMonthlyRptDays[aWeek]&(MapDayToBits(aDay))); 
       
  1344 	}
       
  1345 
       
  1346 
       
  1347 TInt TAgnMonthlyByDaysRpt::NumDaysSet() const
       
  1348 /** Gets the number of repeat days in the month.
       
  1349 
       
  1350 @internalComponent
       
  1351 @return The number of days set. */
       
  1352 	{
       
  1353 
       
  1354 	TInt total = 0;
       
  1355 	for (TUint i = EMonday; i <= ESunday; ++i)
       
  1356 		{
       
  1357 		for (TUint j = EFirst; j <= ELast; ++j)
       
  1358 			{
       
  1359 			if (IsDaySet(static_cast<TDay>(i), static_cast<TWeekInMonth>(j)))
       
  1360 				{
       
  1361 				++total;
       
  1362 				}
       
  1363 			}
       
  1364 		}
       
  1365 
       
  1366 	return (total);
       
  1367 	}
       
  1368 
       
  1369 
       
  1370 TInt TAgnMonthlyByDaysRpt::NumInstancesPerMonth() const
       
  1371 	{
       
  1372 	return (NumDaysSet());
       
  1373 	}	
       
  1374 
       
  1375 TInt TAgnMonthlyByDaysRpt::InvariantL() const
       
  1376 //
       
  1377 // Check that the rpt doesn't violate its invariants
       
  1378 //
       
  1379 	{
       
  1380 
       
  1381 	if (TAgnRpt::InvariantL()==KErrNone && NumDaysSet() > 0)
       
  1382 		return (KErrNone);
       
  1383 
       
  1384 	return (EAgmErrBadRepeat);
       
  1385 	}
       
  1386 
       
  1387 
       
  1388 
       
  1389 void TAgnMonthlyByDaysRpt::InternalizeL(RReadStream& aStream)
       
  1390 /** Internalises the monthly by days repeat object from a read stream.
       
  1391 
       
  1392 @internalComponent
       
  1393 @param aStream Stream from which the object should be internalised. */
       
  1394 	{
       
  1395 	
       
  1396 	TAgnRpt::InternalizeL(aStream);
       
  1397 	aStream >> iMonthlyRptDays[0];
       
  1398 	aStream >> iMonthlyRptDays[1];
       
  1399 	aStream >> iMonthlyRptDays[2];
       
  1400 	aStream >> iMonthlyRptDays[3];
       
  1401 	aStream >> iMonthlyRptDays[4];
       
  1402 	}
       
  1403 
       
  1404 void TAgnMonthlyByDaysRpt::ExternalizeL(RWriteStream& aStream) const
       
  1405 /** Externalises the monthly by days repeat object to a write stream.
       
  1406 
       
  1407 @internalComponent
       
  1408 @param aStream Stream to which the object should be externalised. */
       
  1409 	{
       
  1410 
       
  1411 	TAgnRpt::ExternalizeL(aStream);
       
  1412 	aStream << iMonthlyRptDays[0];
       
  1413 	aStream << iMonthlyRptDays[1];
       
  1414 	aStream << iMonthlyRptDays[2];
       
  1415 	aStream << iMonthlyRptDays[3];
       
  1416 	aStream << iMonthlyRptDays[4];
       
  1417 	}
       
  1418 
       
  1419 TBool TAgnMonthlyByDaysRpt::operator==(const TAgnMonthlyByDaysRpt& aRRule) const
       
  1420 /** Compares two monthly by day repeat objects for equality.
       
  1421 
       
  1422 @internalComponent
       
  1423 @param aRRule The object to be compared.
       
  1424 @return True if all repeat details agree, otherwise False. */
       
  1425 	{
       
  1426 
       
  1427 	return (TAgnRpt::operator==(aRRule) 
       
  1428 			&& iMonthlyRptDays[0]==aRRule.iMonthlyRptDays[0]
       
  1429 			&& iMonthlyRptDays[1]==aRRule.iMonthlyRptDays[1]
       
  1430 			&& iMonthlyRptDays[2]==aRRule.iMonthlyRptDays[2]
       
  1431 			&& iMonthlyRptDays[3]==aRRule.iMonthlyRptDays[3]
       
  1432 			&& iMonthlyRptDays[4]==aRRule.iMonthlyRptDays[4]);
       
  1433 	}
       
  1434 
       
  1435 TBool TAgnMonthlyByDaysRpt::IsAlignedUtcL(const TTime& aDate) const
       
  1436 	{
       
  1437 	TTime localDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  1438 	return IsAlignedRptLocalL(localDate);
       
  1439 	}
       
  1440 	
       
  1441 TBool TAgnMonthlyByDaysRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
  1442 //
       
  1443 // Returns true if aDate falls on an instance generated by the repeat algorithm
       
  1444 // (ignores repeat start/end dates)
       
  1445 //
       
  1446 	{
       
  1447 
       
  1448 	TDateTime dateTime=aDate.DateTime();
       
  1449 
       
  1450 	TInt weekNo=dateTime.Day()/7;
       
  1451 	TDay day = aDate.DayNoInWeek();
       
  1452 
       
  1453 	// First check the first 4 weeks
       
  1454 	if (weekNo < 4 && IsDaySet(day,(TWeekInMonth)weekNo)) 
       
  1455 			return (ETrue);
       
  1456 
       
  1457 	// Now check if aDate is in the last week of the month
       
  1458 	if ((dateTime.Day() >= Time::DaysInMonth(dateTime.Year(),dateTime.Month()) - 7)  && (IsDaySet(day,ELast)))
       
  1459 		{
       
  1460 		if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
  1461 			{
       
  1462 			return EFalse;
       
  1463 			}
       
  1464 		
       
  1465 		return (ETrue);
       
  1466 		}
       
  1467 	
       
  1468 	return (EFalse);
       
  1469 	}
       
  1470 
       
  1471 
       
  1472 TTimeIntervalDays TAgnMonthlyByDaysRpt::NumDaysToNextInstanceFrom(const TTime& aDay) const 
       
  1473 //
       
  1474 // Calculates the number of days between aDay and the *next* day which is set, if there is no
       
  1475 // next day before the end of the month then 0 is returned.
       
  1476 // The calculation proceeds by first determining which week of the month aDay+1 is in and then
       
  1477 // checking the remainder of the days of that week, if an instance cannot be found then all days of
       
  1478 // any of the remaining first 4 weeks are checked, if an instance still hasn't been found than the last
       
  1479 // week is checked - this requires skipping backwards as the 4th and last weeks overlap and may coincide
       
  1480 // exactly in the case ofFebruary in a non-leap year. Further explanations of this are given later on
       
  1481 // nearer to the code.
       
  1482 // i.e. suppose aDay is Sunday of the 2nd week and the 1st day of the week is a Friday and 
       
  1483 // there are 31 days in the month:
       
  1484 //	F S S M T W T    F S S M T W T    F S S M T W T    F S S M T W T   F S S    
       
  1485 //						   S                           <---4th week->
       
  1486 //                                                           <--last week--->
       
  1487 // We start by checking in the 2nd week from Monday onwards until thursday is reached. If an instance
       
  1488 // hasn't been found then we move on to the 3rd week, checking from a Friday onwards until Thursday,
       
  1489 // if an instance hasn't been found the process is repeated with the 4th week. If an instance still hasn't
       
  1490 // been found then we must check the last week which means jumping backwards to what is effectively monday
       
  1491 // of the 4th week.
       
  1492 
       
  1493 	{
       
  1494 
       
  1495 	static const TInt startDayOfMonthFactor[8] = {EMonday,ESunday,ESaturday,EFriday,EThursday,EWednesday,ETuesday};
       
  1496 	
       
  1497 	TInt nextDayFromTheParam = (aDay.DayNoInWeek() + 1) % 7; // checking is exclusive of aDay
       
  1498 	TDateTime dateTime = aDay.DateTime();
       
  1499 	if (dateTime.Day() + 1 == Time::DaysInMonth(dateTime.Year(),dateTime.Month()))
       
  1500 		return (0); // we're on the last day of the month
       
  1501 
       
  1502 	TDateTime temp(dateTime);
       
  1503 	temp.SetDay(0);
       
  1504 	TTime temp2(temp);
       
  1505 	TDay dayAtStartOfMonth = temp2.DayNoInWeek();
       
  1506 
       
  1507 
       
  1508 	// find out what week we're in:
       
  1509 	TInt weekNo = (dateTime.Day() + 1) / 7;
       
  1510 	
       
  1511 	TInt numDaysToNextInstance = 1;
       
  1512 	TInt currentDay = nextDayFromTheParam;
       
  1513 	TInt numDaysInWeekToCheck;
       
  1514 	TInt lowestNumDaysToNextInstanceSoFar = 0;
       
  1515 	// the current week we're in may need partial checking
       
  1516 	if (weekNo < 4)
       
  1517 		{
       
  1518 		numDaysInWeekToCheck = 7 - ((currentDay + startDayOfMonthFactor[dayAtStartOfMonth]) % 7);					
       
  1519 		for (; numDaysInWeekToCheck > 0; --numDaysInWeekToCheck)
       
  1520 			{
       
  1521 			if (IsDaySet((TDay)currentDay,(TWeekInMonth)weekNo))
       
  1522 				{
       
  1523 				if (weekNo == 3) // the 4th week - don't return as this may be bettered by the last week - see later explanation
       
  1524 					{
       
  1525 					if (!lowestNumDaysToNextInstanceSoFar)
       
  1526 						lowestNumDaysToNextInstanceSoFar = numDaysToNextInstance;
       
  1527 					goto doincrement;
       
  1528 					}
       
  1529 				else
       
  1530 					return (numDaysToNextInstance);
       
  1531 				}
       
  1532 doincrement:
       
  1533 			++numDaysToNextInstance;
       
  1534 			if (currentDay == (TInt)ESunday)
       
  1535 				currentDay = (TInt)EMonday;
       
  1536 			else
       
  1537 				++currentDay;
       
  1538 			}			
       
  1539 		}
       
  1540 	++weekNo;
       
  1541 
       
  1542 	// while subsequent weeks need full checking
       
  1543 	currentDay = dayAtStartOfMonth;
       
  1544 	for (numDaysInWeekToCheck = 7; weekNo < 4;)
       
  1545 		{
       
  1546 		if (IsDaySet((TDay)currentDay,TWeekInMonth(weekNo)))
       
  1547 			{
       
  1548 			if (weekNo == 3) // the 4th week - don't return as this may be bettered by the last week - see later explanation
       
  1549 				{
       
  1550 				if (!lowestNumDaysToNextInstanceSoFar)
       
  1551 					lowestNumDaysToNextInstanceSoFar = numDaysToNextInstance;
       
  1552 				goto increment;
       
  1553 				}
       
  1554 			else
       
  1555 				return (numDaysToNextInstance);
       
  1556 			}
       
  1557 		else
       
  1558 increment:
       
  1559 			{
       
  1560 			++numDaysToNextInstance;
       
  1561 			if (currentDay == (TInt)ESunday)
       
  1562 				currentDay = (TInt)EMonday;
       
  1563 			else
       
  1564 				++currentDay;
       
  1565 			if (numDaysInWeekToCheck == 1)
       
  1566 				{
       
  1567 				numDaysInWeekToCheck = 7;
       
  1568 				++weekNo;
       
  1569 				}
       
  1570 			else
       
  1571 				--numDaysInWeekToCheck;
       
  1572 			}
       
  1573 		}
       
  1574 
       
  1575 	
       
  1576 	// if the 1st four weeks have been checked and nothing has been found or if
       
  1577 	// we were in the last week to begin with then check the last week
       
  1578 
       
  1579 	// As an example consider the end of January 1996 with Thursday of the last week being set ...
       
  1580 	// 22 23 24 25 26 27 28 29 30 31
       
  1581 	// M  T  W  T  F  S  S  M  T  W  
       
  1582 	// <------4th week------>
       
  1583 	//       <-------last week----->
       
  1584 	//
       
  1585 	// So the 25th of Jan is an instance, suppose we have just checked the 4th week and 
       
  1586 	// having found no instances are currently positioned on the 29th. We now need to go
       
  1587 	// back and check the last week, hence we need to jump to the 24th and check from there
       
  1588 	// onwards until we find the 25th - consequently the numDaysToNextInstance needs decrementing
       
  1589 	// 5 i.e the difference between 29 and 24.
       
  1590 	// A complication arises if the search started from i.e. the 27th because in this case if
       
  1591 	// we jump all the way back to the 24th to start the search it would wrongly flag the 25
       
  1592 	// as being the *next* instance from where the search starts from - this needs to be taken
       
  1593 	// into consideration so that when we are jumping backwards from the 29th we only jump back
       
  1594 	// as far as the 27 and hence just check the last 5 days in the last week and not all 7 of them
       
  1595 	//
       
  1596 	// Consider the following for another complication - in this case the 4th and last weeks coincide
       
  1597 	// (this complication isn't limited to this case though)
       
  1598 	// days set in 4th week:	|         | |
       
  1599 	//							F S S M T W T
       
  1600 	// days set in last week:   | |         |
       
  1601 	// In this case, if checking is from Saturday onwards then when the 4th week is being checked it will
       
  1602 	// find Wednesday as the next occurrence - but the *next* occurrence is Saturday (of the last week). So
       
  1603 	// Wednesday needs to be remembered in case it can't be bettered upon
       
  1604 
       
  1605 	TInt daysInMonth = Time::DaysInMonth(dateTime.Year(),dateTime.Month());
       
  1606 	TInt dayNumOfTheParam = dateTime.Day() + 1;
       
  1607 	TInt dayNumOf1stDayOfLastWeek = daysInMonth - 7;
       
  1608 	TInt diffBetween1stDayOfLastWeekAndParam = 0;
       
  1609 	if (dayNumOf1stDayOfLastWeek <= dayNumOfTheParam)
       
  1610 		diffBetween1stDayOfLastWeekAndParam = dayNumOfTheParam - dayNumOf1stDayOfLastWeek;		
       
  1611 
       
  1612 	numDaysToNextInstance -= (7 - (daysInMonth - 28));
       
  1613 	numDaysToNextInstance += diffBetween1stDayOfLastWeekAndParam; 
       
  1614 	currentDay = ((TInt)dayAtStartOfMonth + daysInMonth - 7 + diffBetween1stDayOfLastWeekAndParam) % 7; // first day of last week is...
       
  1615 	numDaysInWeekToCheck = 7 - diffBetween1stDayOfLastWeekAndParam;
       
  1616 	while (numDaysInWeekToCheck > 0)
       
  1617 		{
       
  1618 		if (IsDaySet((TDay)currentDay,ELast))
       
  1619 			{
       
  1620 			if (lowestNumDaysToNextInstanceSoFar && lowestNumDaysToNextInstanceSoFar < numDaysToNextInstance)
       
  1621 				numDaysToNextInstance = lowestNumDaysToNextInstanceSoFar;
       
  1622 			return (numDaysToNextInstance);
       
  1623 			}
       
  1624 		
       
  1625 		if (currentDay == (TInt)ESunday)
       
  1626 			currentDay = (TInt)EMonday;
       
  1627 		else
       
  1628 			++currentDay;
       
  1629 		--numDaysInWeekToCheck;
       
  1630 		++numDaysToNextInstance;
       
  1631 		}
       
  1632 
       
  1633 	return (lowestNumDaysToNextInstanceSoFar);
       
  1634 	}
       
  1635 
       
  1636 /*
       
  1637  * Produces the week to check from a specified TTime (Repeat Local).
       
  1638  *
       
  1639  * @param	"const TTime& aTime"
       
  1640  *			The date to check
       
  1641  * @return "TWeekInMonth"
       
  1642  *			The Week to check. If this week is EFourth, you should also check
       
  1643  *			the last week ( ELast ).
       
  1644  */
       
  1645 TAgnRpt::TWeekInMonth TAgnMonthlyByDaysRpt::GetWeekToCheckRptLocal(const TTime& aTime) const
       
  1646 	{
       
  1647 	return static_cast<TAgnRpt::TWeekInMonth>( aTime.DayNoInMonth() / 7 );
       
  1648 	}
       
  1649 
       
  1650 TBool TAgnMonthlyByDaysRpt::CheckLastWeekRptLocal(const TTime& aTime) const
       
  1651 	{
       
  1652 	TInt endOfMonth = aTime.DaysInMonth();
       
  1653 	TInt currentDay = aTime.DayNoInMonth();
       
  1654 	TInt startOfLastWeek = endOfMonth - 7;
       
  1655 	return ( currentDay >= startOfLastWeek );
       
  1656 	}
       
  1657 
       
  1658 
       
  1659 /*
       
  1660  * Returns true, if the specified TTime is a day with an event on it.
       
  1661  *
       
  1662  * @param	"const TTime& aTime"
       
  1663  *			The date to check (Repeat Local)
       
  1664  * @return  "TBool"
       
  1665  *			ETrue if an event occurs on this date
       
  1666  *			EFalse if not.
       
  1667  */
       
  1668 TBool TAgnMonthlyByDaysRpt::EventOnDateRptLocal( const TTime& aTime ) const
       
  1669 	{
       
  1670 	TAgnRpt::TWeekInMonth weekInMonth = GetWeekToCheckRptLocal( aTime );
       
  1671 	TDay dayOfWeek = aTime.DayNoInWeek();
       
  1672 	TBool retval = EFalse;
       
  1673 
       
  1674 	retval = IsDaySet( dayOfWeek, weekInMonth );
       
  1675 
       
  1676 	if (!retval && weekInMonth == TAgnRpt::EFourth && CheckLastWeekRptLocal(aTime))
       
  1677 		{
       
  1678 		retval = IsDaySet( dayOfWeek, TAgnRpt::ELast );
       
  1679 		}
       
  1680 
       
  1681 	return retval;
       
  1682 	}
       
  1683 
       
  1684 
       
  1685 /*
       
  1686  * Find the last event on the specified month.
       
  1687  *
       
  1688  *
       
  1689  * @return  "TTime"
       
  1690  *			The date of the last event (Repeat Local).
       
  1691  *
       
  1692  */
       
  1693 TTime TAgnMonthlyByDaysRpt::FindLastEventOnSpecifiedMonthRptLocal(const TTime& aTime) const
       
  1694 	{
       
  1695 	TTime dateCounter = aTime;
       
  1696 	TTime retval = aTime;
       
  1697 	TDateTime dateTime;
       
  1698 	const TInt KEndDayOfMonth = aTime.DaysInMonth(); // last day of month,..
       
  1699 	const TInt KStartDayInMonth = aTime.DayNoInMonth(); // curent starting day in month
       
  1700 	TInt counter = 0;
       
  1701 
       
  1702 	for (counter = KEndDayOfMonth; counter > KStartDayInMonth; counter--)
       
  1703 		{
       
  1704 		dateTime = dateCounter.DateTime();
       
  1705 		dateTime.SetDay( counter );
       
  1706 		dateCounter = dateTime;
       
  1707 		if ( EventOnDateRptLocal( dateCounter ) )
       
  1708 			{
       
  1709 			retval = dateCounter;
       
  1710 			break;
       
  1711 			}
       
  1712 		}
       
  1713 
       
  1714 	return retval;
       
  1715 	}
       
  1716 	
       
  1717 // ------------------------------- TAgnMonthlyByDatesRpt ------------------------------------------------------
       
  1718 
       
  1719 EXPORT_C TAgnMonthlyByDatesRpt::TAgnMonthlyByDatesRpt(CAgnRptDef& aOwningRptDef) : 
       
  1720 	TAgnMonthlyRpt(aOwningRptDef)
       
  1721 /** Constructs a monthly repeat by dates object. 
       
  1722 
       
  1723 All monthly repeat dates are cleared. 
       
  1724 
       
  1725 @internalComponent
       
  1726 */
       
  1727 	{
       
  1728 	iMonthlyRptDates = 0;
       
  1729 	}
       
  1730 
       
  1731 EXPORT_C TAgnMonthlyByDatesRpt::TAgnMonthlyByDatesRpt(const TAgnMonthlyByDatesRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
  1732 	TAgnMonthlyRpt(aRRule, aOwningRptDef)
       
  1733 /** Constructs a new TAgnMonthlyByDatesRpt object from an existing one.
       
  1734 
       
  1735 @internalComponent
       
  1736 @param aRRule The object to be copied. */
       
  1737 	{
       
  1738 	iMonthlyRptDates = aRRule.iMonthlyRptDates; 
       
  1739 	}
       
  1740 
       
  1741 TAgnRpt::TType TAgnMonthlyByDatesRpt::Type() const
       
  1742 	{
       
  1743 	return TAgnRpt::EMonthlyByDates;
       
  1744 	}
       
  1745 	
       
  1746 EXPORT_C void TAgnMonthlyByDatesRpt::SetDate(TUint aDateInMonth)
       
  1747 /** Sets the date specified.
       
  1748 
       
  1749 @internalComponent
       
  1750 @param aDateInMonth The date to be added, (between 0 and 30 inclusive). */
       
  1751 	{
       
  1752 
       
  1753 	iMonthlyRptDates |= MapDateToBits(aDateInMonth);
       
  1754 	}
       
  1755 
       
  1756 EXPORT_C TBool TAgnMonthlyByDatesRpt::IsDateSet(TUint aDateInMonth) const
       
  1757 /** Tests whether the supplied date is set.
       
  1758 
       
  1759 @internalComponent
       
  1760 @param aDateInMonth The date to be tested for (between 0 and 30 inclusive).
       
  1761 @return True if set, False if not set. */
       
  1762 	{
       
  1763 
       
  1764 	return (iMonthlyRptDates & (MapDateToBits(aDateInMonth))); 
       
  1765 	}
       
  1766 
       
  1767 
       
  1768 TInt TAgnMonthlyByDatesRpt::NumDatesSet() const
       
  1769 /** Gets the number of repeat dates in the month which are set.
       
  1770 
       
  1771 @internalComponent
       
  1772 @return The number of dates set. */
       
  1773 	{
       
  1774 	TInt count = 0;
       
  1775 	for (TUint i = 0; i <= 30; ++i) // check each date in a month
       
  1776 		{
       
  1777 		if (IsDateSet(i))
       
  1778 			{
       
  1779 			++count;
       
  1780 			}
       
  1781 		}
       
  1782 
       
  1783 	return (count);
       
  1784 	}
       
  1785 
       
  1786 TInt TAgnMonthlyByDatesRpt::NumInstancesPerMonth() const
       
  1787 	{
       
  1788 	return (NumDatesSet());
       
  1789 	}
       
  1790 
       
  1791 TInt TAgnMonthlyByDatesRpt::InvariantL() const
       
  1792 //
       
  1793 // Check that the rpt doesn't violate its invariants
       
  1794 //
       
  1795 	{
       
  1796 	if (TAgnRpt::InvariantL()==KErrNone && NumDatesSet() > 0)
       
  1797 		return (KErrNone);
       
  1798 
       
  1799 	return (EAgmErrBadRepeat);
       
  1800 	}
       
  1801 
       
  1802 
       
  1803 
       
  1804 void TAgnMonthlyByDatesRpt::InternalizeL(RReadStream& aStream)
       
  1805 /** Internalises the monthly by date repeat object from a read stream.
       
  1806 
       
  1807 @internalComponent
       
  1808 @param aStream Stream from which the object should be internalised. */
       
  1809 	{
       
  1810 
       
  1811 	TAgnRpt::InternalizeL(aStream);		
       
  1812 	aStream >> iMonthlyRptDates;
       
  1813 	}
       
  1814 
       
  1815 void TAgnMonthlyByDatesRpt::ExternalizeL(RWriteStream& aStream) const
       
  1816 /** Externalises the monthly by date repeat object to a write stream.
       
  1817 
       
  1818 @internalComponent
       
  1819 @param aStream Stream to which the object should be externalised. */
       
  1820 	{
       
  1821 
       
  1822 	TAgnRpt::ExternalizeL(aStream);
       
  1823 	aStream << iMonthlyRptDates;
       
  1824 	}
       
  1825 
       
  1826 TBool TAgnMonthlyByDatesRpt::operator==(const TAgnMonthlyByDatesRpt& aRRule) const
       
  1827 /** Compares two monthly by date repeat objects for equality.
       
  1828 
       
  1829 @internalComponent
       
  1830 @param aRRule The object to be compared.
       
  1831 @return True if all repeat details agree, otherwise False. */
       
  1832 	{
       
  1833 
       
  1834 	return (TAgnRpt::operator==(aRRule) && iMonthlyRptDates==aRRule.iMonthlyRptDates);
       
  1835 	} 
       
  1836 			
       
  1837 TBool TAgnMonthlyByDatesRpt::IsAlignedUtcL(const TTime& aDate) const
       
  1838 //
       
  1839 // Returns true is aDate (UTC) falls on a date generated by the repeat algorithm
       
  1840 // (ignores repeat start/end dates)
       
  1841 //
       
  1842 	{
       
  1843 	TTime localDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  1844 	return IsAlignedRptLocalL(localDate);
       
  1845 	}
       
  1846 	
       
  1847 TBool TAgnMonthlyByDatesRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
  1848 //
       
  1849 // Returns true is aDate (Repeat Local Time) falls on a date generated by the repeat algorithm
       
  1850 // (ignores repeat start/end dates)
       
  1851 //
       
  1852 	{
       
  1853 	TDateTime date = aDate.DateTime();
       
  1854 	
       
  1855 	TUint dayBit = MapDateToBits(date.Day());
       
  1856 	// If the date being checked is, for example, the 30th April and the repeat
       
  1857 	// is set to repeat on the 31st of the month then this is still an aligned
       
  1858 	// date so the high order bits in dayBit need setting to catch this i.e.
       
  1859 	// if 30th april = 0001000... then this needs setting to 11110000
       
  1860 	if (date.Day() == Time::DaysInMonth(date.Year(),date.Month())-1)
       
  1861 		{
       
  1862 		dayBit =~ (dayBit-1); 
       
  1863 		}
       
  1864 
       
  1865 	if ( ! (dayBit & iMonthlyRptDates))
       
  1866 		{
       
  1867 		return EFalse;
       
  1868 		}
       
  1869 
       
  1870 	if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
  1871 		{
       
  1872 		return EFalse;
       
  1873 		}
       
  1874 	
       
  1875 	return ETrue;
       
  1876 	}
       
  1877 
       
  1878 
       
  1879 TTimeIntervalDays TAgnMonthlyByDatesRpt::NumDaysToNextInstanceFrom(const TTime& aDate) const
       
  1880 //
       
  1881 // Calculates the number of days between aDate and the *next* date which is set i.e. if
       
  1882 // the date in aDate is the 2nd of the month, and if the repeat is set to repeat on the
       
  1883 // 5th and 10th of the month then 3 is returned. If there is no subsequent date set then
       
  1884 // 0 is returned.
       
  1885 //
       
  1886 	{
       
  1887 	// Assumes aDate is expressed in Repeat Local Time
       
  1888 		
       
  1889 	TDateTime dateTime = aDate.DateTime();
       
  1890 	TUint daysInMonth = Time::DaysInMonth(dateTime.Year(),dateTime.Month());
       
  1891 	TUint dayInMonth = dateTime.Day() + 1; 
       
  1892 	for (TInt num=1; dayInMonth < 31;++dayInMonth)
       
  1893 		{
       
  1894 		if (IsDateSet(dayInMonth))
       
  1895 			return (num);
       
  1896 		if (dayInMonth < daysInMonth-1)
       
  1897 		// If the date being checked is, for example, the 30th April and the repeat
       
  1898 		// is set to repeat on the 31st of the month then the number to return is the
       
  1899 		// difference between 30 and aDate not 31 and aDate - hence num should not be
       
  1900 		// incremented in this case
       
  1901 			++num;
       
  1902 		}
       
  1903 	return (0);
       
  1904 	}
       
  1905 
       
  1906 
       
  1907 /*
       
  1908  * Find the last event on the first month if the rule begins.
       
  1909  *
       
  1910  *
       
  1911  * @return  "TTime" (Repeat Local)
       
  1912  *			The date of the last event.
       
  1913  *
       
  1914  */
       
  1915 TTime TAgnMonthlyByDatesRpt::FindLastEventOnSpecifiedMonthRptLocal(const TTime& aTime) const
       
  1916 	{
       
  1917 	const TInt KEndDayOfMonth = aTime.DaysInMonth() - 1; // zero initialised
       
  1918 	TTime retval = aTime;
       
  1919 	TInt counter = 0;
       
  1920 	TDateTime lastDay;
       
  1921 
       
  1922 	for (counter = KEndDayOfMonth; counter >= 0; counter--)
       
  1923 		{
       
  1924 		if ( IsDateSet( counter ) )
       
  1925 			{
       
  1926 			lastDay = retval.DateTime();
       
  1927 			lastDay.SetDay( counter );
       
  1928 			retval = lastDay;
       
  1929 			break;
       
  1930 			}
       
  1931 		}
       
  1932 
       
  1933 	return retval;
       
  1934 	}
       
  1935 
       
  1936 // ------------------------------ TAgnYearlyByDateRpt ----------------------------
       
  1937 EXPORT_C TAgnYearlyByDateRpt::TAgnYearlyByDateRpt(CAgnRptDef& aOwningRptDef) : 
       
  1938 	TAgnRpt(aOwningRptDef)
       
  1939 /**
       
  1940 This is not inline to prevent non-exportable functions causing a linker error in calling code
       
  1941 
       
  1942 @internalComponent
       
  1943 */
       
  1944 	{}
       
  1945 
       
  1946 EXPORT_C TAgnYearlyByDateRpt::TAgnYearlyByDateRpt(const TAgnYearlyByDateRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
  1947 	TAgnRpt(aRRule, aOwningRptDef)
       
  1948 /** Constructs a new TAgnYearlyByDateRpt object from an existing one.
       
  1949 
       
  1950 @internalComponent
       
  1951 @param aRRule The object to be copied. */
       
  1952 	{}
       
  1953 
       
  1954 TAgnRpt::TType TAgnYearlyByDateRpt::Type() const
       
  1955 	{
       
  1956 	return TAgnRpt::EYearlyByDate;
       
  1957 	}
       
  1958 
       
  1959 TUint TAgnYearlyByDateRpt::InstanceCountL() const
       
  1960 /** Gets the number of instances generated by the repeat algorithm.
       
  1961 
       
  1962 @internalComponent
       
  1963 @return The number of instances. */
       
  1964 	{
       
  1965 	// Years from start to end divided by the interval
       
  1966 	// Add one for the first year: if start and end are in the same year,
       
  1967 	// we must return 1.
       
  1968 	return ( 1 + UntilTimeAsRptLocalL().YearsFrom(StartTimeAsRptLocalL()).Int()/iInterval );
       
  1969 	}
       
  1970                                         
       
  1971 TBool TAgnYearlyByDateRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
  1972 //
       
  1973 // Returns true if aDate (Repeat Local Time) falls on an instance generated by the repeat algorithm
       
  1974 // (ignores repeat start/end dates)
       
  1975 //
       
  1976 	{
       
  1977 	// All date and time comparisons must be done in Repeat Local
       
  1978 		
       
  1979 	if (StartTimeAsRptLocalL() == aDate)
       
  1980 		return (ETrue);
       
  1981 	TDateTime startDateTime = StartTimeAsRptLocalL().DateTime();
       
  1982 	TDateTime thisDateTime = aDate.DateTime();
       
  1983 	if ( (thisDateTime.Year()-startDateTime.Year() ) % iInterval)
       
  1984 		return (EFalse);
       
  1985 	if (startDateTime.Month()!=thisDateTime.Month())
       
  1986 		return (EFalse);
       
  1987 	if (startDateTime.Day()!=thisDateTime.Day())
       
  1988 		{		
       
  1989 	// finally check for 28/29th February
       
  1990 		if (startDateTime.Month()!=EFebruary)
       
  1991 			return (EFalse);
       
  1992 		if (startDateTime.Day()!=28)
       
  1993 			return (EFalse);
       
  1994 		if (thisDateTime.Day()!=Time::DaysInMonth(thisDateTime.Year(),thisDateTime.Month())-1)
       
  1995 			return (EFalse);
       
  1996 		}
       
  1997 		
       
  1998 	if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
  1999 		{
       
  2000 		return EFalse;
       
  2001 		}
       
  2002 	
       
  2003 	return ETrue;
       
  2004 	}
       
  2005 
       
  2006 TBool TAgnYearlyByDateRpt::IsAlignedUtcL(const TTime& aUtcDate) const
       
  2007 //
       
  2008 // Returns true if aDate (UTC) falls on an instance generated by the repeat algorithm
       
  2009 // (ignores repeat start/end dates)
       
  2010 //
       
  2011 	{
       
  2012 	// convert aDate from UTC to Repeat Local
       
  2013 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aUtcDate);	
       
  2014 	return IsAlignedRptLocalL(rptLocalDate);
       
  2015 	}
       
  2016 
       
  2017 TTime TAgnYearlyByDateRpt::FindRptUntilTimeRptLocalL(TUint aCount) const
       
  2018 	{
       
  2019 	TTime end = StartTimeAsRptLocalL();
       
  2020 	TUint max = (AgnDateTime::MaxDate().YearsFrom(end).Int() + 1) / iInterval;
       
  2021 	if (aCount > max)
       
  2022 		{
       
  2023 		end = AgnDateTime::MaxDate();
       
  2024 		}
       
  2025 	else
       
  2026 		{
       
  2027 		end += TTimeIntervalYears((aCount - 1) * iInterval);	
       
  2028 		}
       
  2029 	return end;
       
  2030 	}
       
  2031 
       
  2032 TTime TAgnYearlyByDateRpt::NudgeNextInstanceUtcL(const TTime& aDate) const
       
  2033 //
       
  2034 // If aDate (UTC) is already a date generated by the repeat algorithm then that is the date returned,
       
  2035 // otherwise the next instance from aDate is returned 
       
  2036 //
       
  2037 	{
       
  2038 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  2039 	rptLocalDate = NudgeNextInstanceRptLocalL(rptLocalDate);
       
  2040 	return ConvertFromRepeatLocalToUtcL(rptLocalDate);
       
  2041 	}
       
  2042 	
       
  2043 TTime TAgnYearlyByDateRpt::NudgeNextInstanceRptLocalL(const TTime& aDate) const
       
  2044 //
       
  2045 // If aDate (Repeat Local Time) is already a date generated by the repeat algorithm then that is the date returned,
       
  2046 // otherwise the next instance from aDate is returned 
       
  2047 //
       
  2048 	{
       
  2049 	TTime next = NudgeNextAlignedStartTimeL(aDate);
       
  2050 	
       
  2051 	if (IsAlignedRptLocalL(next))
       
  2052 		return (next);
       
  2053 	
       
  2054 	TDateTime thisTDateTime=next.DateTime();
       
  2055 	TDateTime startTDateTime=StartTimeAsRptLocalL().DateTime();
       
  2056 
       
  2057 	TTimeIntervalYears years=AgnDateTime::YearsFrom(startTDateTime,thisTDateTime);
       
  2058 	// Add a year, since the next interval is at least one year away
       
  2059 	// This fixes the 'yearly repeating entries on a leap year don't appear
       
  2060 	// on the 29th Feb' bug
       
  2061 	years = (years.Int() +1);
       
  2062 	years=((years.Int()+Interval()-1)/Interval())*Interval();
       
  2063 	AgnDateTime::AddTo(startTDateTime,years);
       
  2064 
       
  2065 	if (AgnDateTime::IsLessThan(startTDateTime,thisTDateTime))
       
  2066 		AgnDateTime::AddTo(startTDateTime,TTimeIntervalYears(Interval()));
       
  2067 
       
  2068 	TTime date = TTime(startTDateTime);
       
  2069 	if ( date > AgnDateTime::MaxDate())
       
  2070 		{
       
  2071 		return (Time::NullTTime());
       
  2072 		}
       
  2073 	
       
  2074 	return date;
       
  2075 	}
       
  2076 
       
  2077 TTime TAgnYearlyByDateRpt::NudgePreviousInstanceUtcL(const TTime& aDate) const
       
  2078 //
       
  2079 // If aDate (UTC) is already a date generated by the repeat algorithm then that is the date returned, 
       
  2080 // otherwise the previous instance is returned 
       
  2081 //
       
  2082 	{
       
  2083 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  2084 	rptLocalDate = NudgePreviousInstanceRptLocalL(rptLocalDate);
       
  2085 	return ConvertFromRepeatLocalToUtcL(rptLocalDate);
       
  2086 	}
       
  2087 
       
  2088 TTime TAgnYearlyByDateRpt::NudgePreviousInstanceRptLocalL(const TTime& aDate) const
       
  2089 //
       
  2090 // If aDate (Repeat Local Time) is already a date generated by the repeat algorithm then that is the date returned, 
       
  2091 // otherwise the previous instance is returned 
       
  2092 //
       
  2093 	{
       
  2094 	TTime prev = NudgePreviousAlignedStartTimeL(aDate);
       
  2095 	
       
  2096 	if (IsAlignedRptLocalL(prev))
       
  2097 		return (prev);
       
  2098 
       
  2099 	TDateTime thisTDateTime = prev.DateTime();
       
  2100 	TDateTime startTDateTime = StartTimeAsRptLocalL().DateTime();
       
  2101 
       
  2102 	TTimeIntervalYears years=AgnDateTime::YearsFrom(startTDateTime,thisTDateTime);
       
  2103 
       
  2104 	if (years.Int()>=(TInt)Interval())
       
  2105 		{
       
  2106 		years=(years.Int()/Interval())*Interval();
       
  2107 		AgnDateTime::AddTo(startTDateTime,years);
       
  2108 		}
       
  2109 
       
  2110 	TTime date = TTime(startTDateTime);
       
  2111 	if (date < AgnDateTime::MinDate())
       
  2112 		{
       
  2113 		return (Time::NullTTime());
       
  2114 		}
       
  2115 
       
  2116 	return date;
       
  2117 	}
       
  2118 
       
  2119 
       
  2120 // ------------------------------ TAgnYearlyByDayRpt ----------------------------
       
  2121 EXPORT_C TAgnYearlyByDayRpt::TAgnYearlyByDayRpt(CAgnRptDef& aOwningRptDef) : 
       
  2122 	TAgnRpt(aOwningRptDef)
       
  2123 /**
       
  2124 This is not inline to prevent non-exportable functions causing a linker error in calling code
       
  2125 
       
  2126 @internalComponent
       
  2127 */
       
  2128 	{
       
  2129 	iWeekInMonth = static_cast<TAgnRpt::TWeekInMonth>(0);
       
  2130 	iDay = static_cast<TDay>(0);
       
  2131 	}
       
  2132 
       
  2133 EXPORT_C TAgnYearlyByDayRpt::TAgnYearlyByDayRpt(const TAgnYearlyByDayRpt& aRRule, CAgnRptDef& aOwningRptDef) : 
       
  2134 	TAgnRpt(aRRule, aOwningRptDef)
       
  2135 /** Constructs a new TAgnYearlyByDayRpt object from an existing one.
       
  2136 
       
  2137 @internalComponent
       
  2138 @param aRRule The object to be copied. */
       
  2139 	{
       
  2140 	iWeekInMonth = aRRule.iWeekInMonth;
       
  2141 	iDay = aRRule.iDay;
       
  2142 	}
       
  2143 
       
  2144 TAgnRpt::TType TAgnYearlyByDayRpt::Type() const
       
  2145 	{
       
  2146 	return TAgnRpt::EYearlyByDay;
       
  2147 	}
       
  2148 	
       
  2149 TUint TAgnYearlyByDayRpt::InstanceCountL() const
       
  2150 /** Gets the number of yearly repeat instances.
       
  2151 
       
  2152 @internalComponent
       
  2153 @return The number of instances. */
       
  2154  	{
       
  2155 
       
  2156 	TTime UntilTime = UntilTimeAsRptLocalL();
       
  2157 	TTime strtDate= StartTimeAsRptLocalL();
       
  2158 	 for (TInt count = 1; count <= 7; ++count)
       
  2159 		{
       
  2160 		if (UntilTime.DayNoInWeek()==iDay)
       
  2161 			break;
       
  2162 		else
       
  2163 			UntilTime -= TTimeIntervalDays(1);
       
  2164 		}
       
  2165        
       
  2166    	return 1 + ( (UntilTime.DateTime().Year() - strtDate.DateTime().Year()) /Interval()); 
       
  2167 	}
       
  2168 
       
  2169 TBool TAgnYearlyByDayRpt::IsAlignedUtcL(const TTime& aDate) const
       
  2170 //
       
  2171 // Returns true if aDate (UTC) falls on an instance generated by the repeat algorithm
       
  2172 // (ignores repeat start/end dates)
       
  2173 //
       
  2174 	{
       
  2175 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  2176 	return IsAlignedRptLocalL(rptLocalDate);
       
  2177 	}
       
  2178 	
       
  2179 TBool TAgnYearlyByDayRpt::IsAlignedRptLocalL(const TTime& aDate) const
       
  2180 //
       
  2181 // Returns true if aDate (Repeat Local Time) falls on an instance generated by the repeat algorithm
       
  2182 // (ignores repeat start/end dates)
       
  2183 //
       
  2184 	{
       
  2185 
       
  2186 	if (StartTimeAsRptLocalL() == aDate)
       
  2187 		return (ETrue);
       
  2188 
       
  2189 	TDateTime startDateTime = StartTimeAsRptLocalL().DateTime();
       
  2190 	TDateTime thisDateTime = aDate.DateTime();
       
  2191 	if ((thisDateTime.Year()-startDateTime.Year())%Interval())
       
  2192 		return (EFalse);
       
  2193 
       
  2194 	if (startDateTime.Month()!=thisDateTime.Month())
       
  2195 		return (EFalse);
       
  2196 	
       
  2197 	if (aDate.DayNoInWeek()!=iDay)
       
  2198 		return (EFalse);
       
  2199 
       
  2200 	TInt dayInMonth = aDate.DayNoInMonth();
       
  2201 	switch (iWeekInMonth)
       
  2202 		{
       
  2203 		case EFirst:
       
  2204 			{
       
  2205 			if (dayInMonth > 6)
       
  2206 				return (EFalse);
       
  2207 			break;
       
  2208 			}
       
  2209 		case ESecond:
       
  2210 			{
       
  2211 			if (dayInMonth < 7 || dayInMonth > 13)
       
  2212 				return (EFalse);
       
  2213 			break;
       
  2214 			}
       
  2215 		case EThird:
       
  2216 			{
       
  2217 			if (dayInMonth < 14 || dayInMonth > 20)
       
  2218 				return (EFalse);
       
  2219 			break;
       
  2220 			}
       
  2221 		case EFourth:
       
  2222 			{
       
  2223 			if (dayInMonth < 21 || dayInMonth > 27)
       
  2224 				return (EFalse);
       
  2225 			break;
       
  2226 			}
       
  2227 		case ELast:
       
  2228 			{
       
  2229 			if (dayInMonth < aDate.DaysInMonth() - 7)
       
  2230 				return (EFalse);
       
  2231 			break;
       
  2232 			}
       
  2233 		default: 
       
  2234 			{
       
  2235 			_DBGLOG_ENTRY(AgmDebug::DebugLog("TAgnYearlyByDayRpt: Panic - EAgmErrInvalidWeekNumber");)
       
  2236 			DBG_PANIC(EAgmErrInvalidWeekNumber);
       
  2237 			}
       
  2238 		}
       
  2239 
       
  2240 	if (HourAndMinutesDifferentFromStartTimeL(aDate))
       
  2241 		{
       
  2242 		return EFalse;
       
  2243 		}
       
  2244 	
       
  2245 	return (ETrue);
       
  2246 	}
       
  2247 
       
  2248 TTime TAgnYearlyByDayRpt::FindRptUntilTimeRptLocalL(TUint aCount) const
       
  2249 	{
       
  2250 	// do all calculations in Repeat Local times, and convert to UTC before returning
       
  2251 	
       
  2252 	TUint max = AgnDateTime::MaxDate().YearsFrom(StartTimeAsRptLocalL()).Int();
       
  2253 	
       
  2254 	TUint count = aCount > max ? max : aCount;
       
  2255 
       
  2256 	TTime end=StartTimeAsRptLocalL();
       
  2257 	end+=TTimeIntervalYears((count-1)*Interval());
       
  2258 
       
  2259 	TDateTime dt = end.DateTime();
       
  2260 	TInt firstDay = GetFirstDayInWeekRptLocal(iWeekInMonth,dt.Month(),dt.Year());
       
  2261 	dt.SetDay(firstDay);
       
  2262 	end = dt;
       
  2263 	SetDateAccordingToDayRptLocal(end,iDay,iWeekInMonth);
       
  2264 
       
  2265 	return end;
       
  2266 	}
       
  2267 
       
  2268 TTime TAgnYearlyByDayRpt::NudgeNextInstanceUtcL(const TTime& aDate) const
       
  2269 //
       
  2270 // If aDate (UTC) is already a date generated by the repeat algorithm then that is the date returned,
       
  2271 // otherwise the next instance from aDate is returned.
       
  2272 // Complication:
       
  2273 // Suppose an entry starts on the 29 th of a month in year X
       
  2274 // 29 X ....	27 28 Y .....	26 Z
       
  2275 // I            I  a			I
       
  2276 // if aDate is 28th Y then because 26 Z is less than a year from a the calculation will be in
       
  2277 // error unless  a is advanced to compensate.
       
  2278 //
       
  2279 	{
       
  2280 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  2281 	rptLocalDate = NudgeNextInstanceRptLocalL(rptLocalDate);
       
  2282 	return ConvertFromRepeatLocalToUtcL(rptLocalDate);
       
  2283 	}
       
  2284 	
       
  2285 TTime TAgnYearlyByDayRpt::NudgeNextInstanceRptLocalL(TTime aDate) const
       
  2286 //
       
  2287 // If aDate (Repeat Local Time) is already a date generated by the repeat algorithm then that is the date returned,
       
  2288 // otherwise the next instance from aDate is returned.
       
  2289 // Complication:
       
  2290 // Suppose an entry starts on the 29 th of a month in year X
       
  2291 // 29 X ....	27 28 Y .....	26 Z
       
  2292 // I            I  a			I
       
  2293 // if aDate is 28th Y then because 26 Z is less than a year from a the calculation will be in
       
  2294 // error unless  a is advanced to compensate.
       
  2295 //
       
  2296 	{
       
  2297 	TTime ttime = NudgeNextAlignedStartTimeL(aDate);
       
  2298 	
       
  2299 	for (TInt count = 1; count <= 7; ++count)
       
  2300 		{
       
  2301 		if (ttime.DayNoInWeek()==iDay)
       
  2302 			break;
       
  2303 		else
       
  2304 			ttime += TTimeIntervalDays(1);
       
  2305 		}
       
  2306 
       
  2307 	if (ttime > AgnDateTime::MaxDate()) 
       
  2308 		return (Time::NullTTime());
       
  2309 
       
  2310 	aDate = ttime;
       
  2311 	if (IsAlignedRptLocalL(aDate))
       
  2312 		return (aDate);
       
  2313 
       
  2314 	TDateTime thisTDateTime = aDate.DateTime();
       
  2315 	TDateTime startTDateTime = StartTimeAsRptLocalL().DateTime();
       
  2316 
       
  2317 	TTimeIntervalYears years=AgnDateTime::YearsFrom(startTDateTime,thisTDateTime);
       
  2318 	years=((years.Int()+Interval()-1)/Interval())*Interval();
       
  2319 	AgnDateTime::AddTo(startTDateTime,years);
       
  2320 
       
  2321 	if (AgnDateTime::IsLessThan(startTDateTime,thisTDateTime))
       
  2322 		AgnDateTime::AddTo(startTDateTime,TTimeIntervalYears(Interval()));
       
  2323 
       
  2324 	TInt firstDay = GetFirstDayInWeekRptLocal(iWeekInMonth,startTDateTime.Month(),startTDateTime.Year());
       
  2325 	startTDateTime.SetDay(firstDay);
       
  2326 	ttime = startTDateTime;
       
  2327 	SetDateAccordingToDayRptLocal(ttime,iDay,iWeekInMonth);
       
  2328 
       
  2329 	if (ttime > AgnDateTime::MaxDate())
       
  2330 		return (Time::NullTTime());
       
  2331 
       
  2332 	return ttime;
       
  2333 	}
       
  2334 
       
  2335 TTime TAgnYearlyByDayRpt::NudgePreviousInstanceUtcL(const TTime& aDate) const
       
  2336 //
       
  2337 // If aDate (UTC) is already a date generated by the repeat algorithm then that is the date returned, 
       
  2338 // otherwise the previous instance is returned 
       
  2339 //
       
  2340 // Complication:
       
  2341 // Suppose the repeat starts on the 1st of January year X and an instance is on 5th January year Y
       
  2342 //		1 X ........................1 2 3 4 5 6 7 8 Y
       
  2343 //		s							a	b	I	  d
       
  2344 // Now if bis choosen as the point to nudge from there is no problem, but suppose b is the date
       
  2345 // to nudge from then if the number of years between b and s is calculated the it will be 1 too many
       
  2346 // because a is more than 365 day after s (assuming Y = X + 1). So if aDate is b then it needs to be
       
  2347 // reduced to < a to find the correct previous instance.
       
  2348 	{
       
  2349 	TTime rptLocalDate = ConvertFromUtcToRepeatLocalL(aDate);
       
  2350 	rptLocalDate = NudgePreviousInstanceRptLocalL(rptLocalDate);
       
  2351 	return ConvertFromRepeatLocalToUtcL(rptLocalDate);
       
  2352 	}
       
  2353 
       
  2354 TTime TAgnYearlyByDayRpt::NudgePreviousInstanceRptLocalL(TTime aDate) const
       
  2355 //
       
  2356 // If aDate (Repeat Local Time) is already a date generated by the repeat algorithm then that is the date returned, 
       
  2357 // otherwise the previous instance is returned 
       
  2358 //
       
  2359 // Complication:
       
  2360 // Suppose the repeat starts on the 1st of January year X and an instance is on 5th January year Y
       
  2361 //		1 X ........................1 2 3 4 5 6 7 8 Y
       
  2362 //		s							a	b	I	  d
       
  2363 // Now if bis choosen as the point to nudge from there is no problem, but suppose b is the date
       
  2364 // to nudge from then if the number of years between b and s is calculated the it will be 1 too many
       
  2365 // because a is more than 365 day after s (assuming Y = X + 1). So if aDate is b then it needs to be
       
  2366 // reduced to < a to find the correct previous instance.
       
  2367 
       
  2368 	{
       
  2369 
       
  2370 	TTime ttime = NudgePreviousAlignedStartTimeL(aDate);
       
  2371 	for (TInt count = 1; count <= 7; ++count)
       
  2372 		{
       
  2373 		if (ttime.DayNoInWeek()==iDay)
       
  2374 			break;
       
  2375 		else
       
  2376 			ttime -= TTimeIntervalDays(1);
       
  2377 		}
       
  2378 
       
  2379 	aDate = ttime;
       
  2380 	if (IsAlignedRptLocalL(aDate))
       
  2381 		return (aDate);
       
  2382 
       
  2383 	TDateTime thisTDateTime = aDate.DateTime();
       
  2384 	TDateTime startTDateTime = StartTimeAsRptLocalL().DateTime();
       
  2385 
       
  2386 	TTimeIntervalYears years=AgnDateTime::YearsFrom(startTDateTime,thisTDateTime);
       
  2387 
       
  2388 	if (years.Int()>=(TInt)Interval())
       
  2389 		{
       
  2390 		years=(years.Int()/Interval())*Interval();
       
  2391 		AgnDateTime::AddTo(startTDateTime,years);
       
  2392 		}
       
  2393 
       
  2394 	TInt firstDay = GetFirstDayInWeekRptLocal(iWeekInMonth,startTDateTime.Month(),startTDateTime.Year());
       
  2395 	startTDateTime.SetDay(firstDay);
       
  2396 	ttime = startTDateTime;
       
  2397 	SetDateAccordingToDayRptLocal(ttime,iDay,iWeekInMonth);
       
  2398 
       
  2399 	if (ttime < AgnDateTime::MinDate())
       
  2400 		return (Time::NullTTime());
       
  2401 
       
  2402 	return ttime;
       
  2403 	}
       
  2404 
       
  2405 
       
  2406 TInt TAgnYearlyByDayRpt::GetFirstDayInWeekRptLocal(TWeekInMonth aWeekInMonth,TMonth aMonth, TInt aYear) const
       
  2407 //
       
  2408 // Return the day number for the first day in the week aWeekInMonth
       
  2409 //
       
  2410 	{
       
  2411 
       
  2412 	TInt day=0;
       
  2413 	switch (aWeekInMonth)
       
  2414 		{
       
  2415 		case EFirst:	day= 0;	break;
       
  2416 		case ESecond:	day= 7;	break;
       
  2417 		case EThird:	day= 14; break;
       
  2418 		case EFourth:	day= 21; break;
       
  2419 		case ELast:		day= Time::DaysInMonth(aYear,aMonth) - 1; break;						
       
  2420 		default:
       
  2421 			{
       
  2422 			_DBGLOG_ENTRY(AgmDebug::DebugLog("TAgnYearlyByDayRpt: Panic - EAgmErrInvalidWeekNumber");)
       
  2423 			DBG_PANIC(EAgmErrInvalidWeekNumber);
       
  2424 			}
       
  2425 		}
       
  2426 	return (day);
       
  2427 	}
       
  2428 
       
  2429 void TAgnYearlyByDayRpt::SetDateAccordingToDayRptLocal(TTime& aDate,TDay aDay,TWeekInMonth aWeekInMonth) const
       
  2430 //
       
  2431 // Adjust aDate (Repeat Local Time) until its day of the week (i.e. tuesday) corresponds with aDay
       
  2432 //
       
  2433 	{
       
  2434 
       
  2435 	for(TInt count = 1; count <= 7; ++count)
       
  2436 		{
       
  2437 		if (aDate.DayNoInWeek()==aDay)
       
  2438 			break;
       
  2439 		else
       
  2440 			{
       
  2441 			if (aWeekInMonth == ELast)
       
  2442 				aDate -= TTimeIntervalDays(1);
       
  2443 			else
       
  2444 				aDate += TTimeIntervalDays(1);
       
  2445 			}
       
  2446 		}
       
  2447 	}
       
  2448 
       
  2449 
       
  2450 EXPORT_C TTime TAgnYearlyByDayRpt::FindStartDayL(TDay aDay,TWeekInMonth aWeek,TMonth aMonth,TInt aYear)
       
  2451 /** Sets the repeat's start date using the details specified. These details are assumed to refer
       
  2452 to the time zone where the repeating activity takes place.
       
  2453 
       
  2454 @internalComponent
       
  2455 @param aDay The start day.
       
  2456 @param aWeek The start week in the month.
       
  2457 @param aMonth The start month.
       
  2458 @param aYear The start year. */
       
  2459 	{
       
  2460 
       
  2461 	iWeekInMonth = aWeek;
       
  2462 	iDay = aDay;
       
  2463 	TInt dayInMonth=GetFirstDayInWeekRptLocal(aWeek,aMonth,aYear);
       
  2464 	TDateTime startDT = StartTimeAsRptLocalL().DateTime();
       
  2465 	TTime date(TDateTime(aYear,aMonth,dayInMonth,startDT.Hour(),startDT.Minute(),startDT.Second(),startDT.MicroSecond()));	
       
  2466 	SetDateAccordingToDayRptLocal(date,aDay,aWeek);
       
  2467 	return date;
       
  2468 	}
       
  2469 
       
  2470 EXPORT_C void TAgnYearlyByDayRpt::GetStartDayL(TDay& aDay,TWeekInMonth& aWeek,TMonth& aMonth,TInt& aYear) const
       
  2471 /** Gets the start day, week, month and year for the current start date. These details refer
       
  2472 to the time zone where the repeating entry takes place, not the time zone where the user is.
       
  2473 
       
  2474 @internalComponent
       
  2475 @param aDay On return, the start day.
       
  2476 @param aWeek On return, the week in the month of the start date.
       
  2477 @param aMonth On return, the month of the start date.
       
  2478 @param aYear On return, the year of the start date. */
       
  2479 	{
       
  2480 
       
  2481 	TTime date = StartTimeAsRptLocalL(); // Repeat Local
       
  2482 	aDay = date.DayNoInWeek();
       
  2483 	aWeek = iWeekInMonth;
       
  2484 	TDateTime dateTime = date.DateTime();
       
  2485 	aMonth = dateTime.Month();
       
  2486 	aYear = dateTime.Year();	
       
  2487 	}
       
  2488 
       
  2489 
       
  2490 void TAgnYearlyByDayRpt::InternalizeL(RReadStream& aStream)
       
  2491 /** Internalises the yearly by day repeat object from a read stream.
       
  2492 
       
  2493 @internalComponent
       
  2494 @param aStream Stream from which the object should be internalised. */
       
  2495 	{
       
  2496 	TAgnRpt::InternalizeL(aStream);
       
  2497 	iWeekInMonth = TWeekInMonth(aStream.ReadUint8L());	
       
  2498 			
       
  2499 	iDay = TDay(aStream.ReadUint8L());
       
  2500 	}
       
  2501 	
       
  2502 void TAgnYearlyByDayRpt::ExternalizeL(RWriteStream& aStream) const
       
  2503 /** Externalises the yearly by day repeat object to a write stream.
       
  2504 
       
  2505 @internalComponent
       
  2506 @param aStream Stream to which the object should be externalised. */
       
  2507 	{
       
  2508 	TAgnRpt::ExternalizeL(aStream);
       
  2509 	aStream.WriteUint8L(iWeekInMonth);
       
  2510 	aStream.WriteUint8L(iDay);
       
  2511 	}
       
  2512 
       
  2513 
       
  2514 TInt TAgnYearlyByDayRpt::InvariantL() const
       
  2515 //
       
  2516 // Check that the rpt doesn't violate its invariants
       
  2517 //
       
  2518 	{
       
  2519 
       
  2520 
       
  2521 	if (TAgnRpt::InvariantL()==KErrNone && (iWeekInMonth == EFirst || iWeekInMonth == ESecond
       
  2522 			|| iWeekInMonth == EThird || iWeekInMonth == EFourth || iWeekInMonth == ELast) &&
       
  2523 			(iDay == EMonday || iDay == ETuesday || iDay == EWednesday || iDay == EThursday ||
       
  2524 			iDay == EFriday || iDay == ESaturday || iDay == ESunday))
       
  2525 		return (KErrNone);
       
  2526 
       
  2527 	return (EAgmErrBadRepeat);
       
  2528 	}
       
  2529 
       
  2530 
       
  2531 // --------------------------------------- CAgnRptDef -------------------------------
       
  2532 
       
  2533 CAgnRptDef::CAgnRptDef(const CAgnSimpleEntry& aOwningEntry) :
       
  2534 	iOwningEntry(aOwningEntry)
       
  2535 	{
       
  2536 	}
       
  2537 
       
  2538 /** Gets the first instance of the repeat as a TAgnCalendarTime.
       
  2539 This is either the first sporadic date or the start of the repeat rule, whichever is earlier.
       
  2540 
       
  2541 @return The first instance of the repeat.
       
  2542 @internalComponent
       
  2543 */
       
  2544 EXPORT_C const TAgnCalendarTime& CAgnRptDef::FirstInstanceL() const
       
  2545 	{
       
  2546 	if (!HasRepeatRule() && !HasSporadicDates())
       
  2547 		{
       
  2548 		User::Leave(KErrCorrupt);
       
  2549 		}
       
  2550 		
       
  2551 	if (HasRepeatRule() && !HasSporadicDates())
       
  2552 		{
       
  2553 		return StartTime(); 
       
  2554 		}
       
  2555 	else if (!HasRepeatRule() && HasSporadicDates())
       
  2556 		{
       
  2557 		return (*iSporadicDates)[0]; 
       
  2558 		}
       
  2559 	
       
  2560 	// has both rule and rdates	
       
  2561 	const TAgnCalendarTime& KRuleFirstDate = StartTime();   
       
  2562 	const TAgnCalendarTime& KRdateFirstDate = (*iSporadicDates)[0];  
       
  2563 	
       
  2564 	return KRuleFirstDate < KRdateFirstDate ? KRuleFirstDate : KRdateFirstDate;
       
  2565 	}
       
  2566 
       
  2567 /** Gets the last instance of the repeat as a TAgnCalendarTime.
       
  2568 This is either the last sporadic date or the end of the repeat rule, whichever is latest.
       
  2569 
       
  2570 @return The last instance of the repeat.
       
  2571 @internalComponent
       
  2572 */
       
  2573 EXPORT_C const TAgnCalendarTime& CAgnRptDef::LastInstanceL() const
       
  2574 	{
       
  2575 	if (!HasRepeatRule() && !HasSporadicDates())
       
  2576 		{
       
  2577 		User::Leave(KErrCorrupt);
       
  2578 		}
       
  2579 	
       
  2580 	if (HasRepeatRule() && !HasSporadicDates())
       
  2581 		{
       
  2582 		return iRRule->UntilTimeL(); 
       
  2583 		}
       
  2584 	else if (!HasRepeatRule() && HasSporadicDates())
       
  2585 		{
       
  2586 		return (*iSporadicDates)[iSporadicDates->Count() - 1]; 
       
  2587 		}
       
  2588 	
       
  2589 	// has both rule and rdates	
       
  2590 	const TAgnCalendarTime& KRuleLastDate = iRRule->UntilTimeL();   
       
  2591 	const TAgnCalendarTime& KRdateLastDate = (*iSporadicDates)[iSporadicDates->Count() - 1]; 
       
  2592 	return KRuleLastDate > KRdateLastDate ? KRuleLastDate : KRdateLastDate;
       
  2593 	}
       
  2594 
       
  2595 EXPORT_C void CAgnRptDef::SetRRuleL(const TAgnRpt& aRRule)
       
  2596 	{
       
  2597 	CreateRptObjectL(aRRule);
       
  2598 	}
       
  2599 
       
  2600 /** Create a Repeat Rule of the appropriate repeat rule type operator.
       
  2601 @param aRRule  Repeat details. */
       
  2602 void CAgnRptDef::CreateRptObjectL(const TAgnRpt& aRRule)
       
  2603 	{
       
  2604 	delete iRRule;
       
  2605 	iRRule = NULL;
       
  2606 	
       
  2607 	switch (aRRule.Type())
       
  2608 		{
       
  2609 		case TAgnRpt::EDaily:			
       
  2610 			iRRule = new (ELeave) TAgnDailyRpt( static_cast<const TAgnDailyRpt&>(aRRule), *this );
       
  2611 			break;
       
  2612 
       
  2613 		case TAgnRpt::EWeekly:			
       
  2614 			iRRule = new (ELeave) TAgnWeeklyRpt( static_cast<const TAgnWeeklyRpt&>(aRRule), *this );
       
  2615 			break;
       
  2616 
       
  2617 		case TAgnRpt::EMonthlyByDays:	
       
  2618 			iRRule = new (ELeave) TAgnMonthlyByDaysRpt( static_cast<const TAgnMonthlyByDaysRpt&>(aRRule), *this );
       
  2619 			break;
       
  2620 
       
  2621 		case TAgnRpt::EMonthlyByDates:	
       
  2622 			iRRule = new (ELeave) TAgnMonthlyByDatesRpt( static_cast<const TAgnMonthlyByDatesRpt&>(aRRule), *this );
       
  2623 			break;
       
  2624 
       
  2625 		case TAgnRpt::EYearlyByDate:		
       
  2626 			iRRule = new (ELeave) TAgnYearlyByDateRpt( static_cast<const TAgnYearlyByDateRpt&>(aRRule), *this );
       
  2627 			break;
       
  2628 
       
  2629 		case TAgnRpt::EYearlyByDay:		
       
  2630 			iRRule = new (ELeave) TAgnYearlyByDayRpt( static_cast<const TAgnYearlyByDayRpt&>(aRRule), *this );
       
  2631 			break;
       
  2632 
       
  2633 		default:
       
  2634 			{
       
  2635 			_DBGLOG_ENTRY(AgmDebug::DebugLog("CAgnRptDef: Panic - EAgmErrInvalidRptType");)
       
  2636 			DBG_PANIC(EAgmErrInvalidRptType);
       
  2637 			break;
       
  2638 			}	
       
  2639 		}
       
  2640 	}
       
  2641 	
       
  2642 void CAgnRptDef::CreateRptObjectL(TAgnRpt::TType aType)
       
  2643 //
       
  2644 // Creates an object of the appropriate repeat rule type
       
  2645 // operator.
       
  2646 //
       
  2647 	{
       
  2648 	delete iRRule;
       
  2649 	iRRule = NULL;
       
  2650 
       
  2651 	switch (aType)
       
  2652 		{
       
  2653 		case TAgnRpt::EDaily:			
       
  2654 			iRRule = new (ELeave) TAgnDailyRpt(*this);
       
  2655 			break;
       
  2656 			
       
  2657 		case TAgnRpt::EWeekly:			
       
  2658 			iRRule = new (ELeave) TAgnWeeklyRpt(*this);
       
  2659 			break;
       
  2660 			
       
  2661 		case TAgnRpt::EMonthlyByDays:	
       
  2662 			iRRule = new (ELeave) TAgnMonthlyByDaysRpt(*this);
       
  2663 			break;
       
  2664 			
       
  2665 		case TAgnRpt::EMonthlyByDates:	
       
  2666 			iRRule = new (ELeave) TAgnMonthlyByDatesRpt(*this);
       
  2667 			break;
       
  2668 			
       
  2669 		case TAgnRpt::EYearlyByDate:		
       
  2670 			iRRule = new (ELeave) TAgnYearlyByDateRpt(*this);
       
  2671 			break;
       
  2672 			
       
  2673 		case TAgnRpt::EYearlyByDay:		
       
  2674 			iRRule = new (ELeave) TAgnYearlyByDayRpt(*this);
       
  2675 			break;
       
  2676 			
       
  2677 		default:
       
  2678 			{
       
  2679 			_DBGLOG_ENTRY(AgmDebug::DebugLog("CAgnRptDef: Panic - EAgmErrInvalidRptType");)
       
  2680 			DBG_PANIC(EAgmErrInvalidRptType);
       
  2681 			break;
       
  2682 			}
       
  2683 		}
       
  2684 
       
  2685 	}
       
  2686 
       
  2687 EXPORT_C CAgnRptDef* CAgnRptDef::NewL(const CAgnSimpleEntry& aOwningEntry)
       
  2688 /** Allocates and constructs a repeat definition.
       
  2689 
       
  2690 @internalComponent
       
  2691 @return Pointer to the created repeat definition. */
       
  2692 	{
       
  2693 	return new (ELeave) CAgnRptDef(aOwningEntry);
       
  2694 	}
       
  2695 
       
  2696 EXPORT_C CAgnRptDef::~CAgnRptDef()
       
  2697 /** Frees all resources owned by the repeat definition, prior to 
       
  2698 its destruction. 
       
  2699 
       
  2700 @internalComponent
       
  2701 */
       
  2702 	{
       
  2703 	delete iRRule;
       
  2704 	delete iTimeZone;
       
  2705 
       
  2706 	ClearTimeArray(iSporadicDates);
       
  2707 	ClearTimeArray(iExceptions);
       
  2708 	}
       
  2709 	
       
  2710 EXPORT_C void CAgnRptDef::AddExceptionL(const TAgnCalendarTime& aException)
       
  2711 /** Adds an exception to the list of exceptions (first creating the exception list 
       
  2712 if necessary).
       
  2713 
       
  2714 @internalComponent
       
  2715 @param aException The exception to add to the list. */
       
  2716 	{
       
  2717 	TAgnCalendarTime exceptionToAdd = aException;
       
  2718 	
       
  2719 	// MS Outlook exports exception dates without time information, i.e. time is reset to midnight.
       
  2720 	// Need to nudge to see if a date occurs on that day.
       
  2721 	if (!IsAnInstanceL(aException.LocalL()))
       
  2722 		{
       
  2723 		TTime exDateUtc = aException.UtcL();
       
  2724 		TTime actualInstanceTimeUtc;
       
  2725 		if (NudgeNextInstanceUtcL(exDateUtc, actualInstanceTimeUtc))
       
  2726 			{
       
  2727 			TTime exDateRepeatLocal = ConvertFromUtcToRepeatLocalL(exDateUtc);
       
  2728 			TTime actualInstanceTimeRepeatLocal = ConvertFromUtcToRepeatLocalL(actualInstanceTimeUtc);
       
  2729 
       
  2730 			// Only change exception date if nudged date is the same date in repeat local time
       
  2731 			if (AgnDateTime::DaysBetweenDates(actualInstanceTimeRepeatLocal, exDateRepeatLocal) == 0)
       
  2732 				{
       
  2733 				if (aException.TimeMode() != MAgnCalendarTimeMode::EFloating)
       
  2734 					{
       
  2735 					exceptionToAdd.SetUtcL(actualInstanceTimeUtc);
       
  2736 					}
       
  2737 				else
       
  2738 					{
       
  2739 					exceptionToAdd.SetFloatingL(actualInstanceTimeRepeatLocal);
       
  2740 					}
       
  2741 				}
       
  2742 			}
       
  2743 		}
       
  2744 		
       
  2745 	if (IsAnInstanceL(exceptionToAdd.LocalL()))
       
  2746 		{
       
  2747 		EnsureTimeArrayExistsL(iExceptions);
       
  2748 		TAgnCalendarTime::InsertInOrderL(*iExceptions, exceptionToAdd);
       
  2749 		}
       
  2750 	}
       
  2751 
       
  2752 EXPORT_C void CAgnRptDef::PruneExceptionsL()
       
  2753 /** Removes any exceptions which do not occur on instances
       
  2754 @internalComponent
       
  2755 */
       
  2756 	{
       
  2757 	if (iExceptions)
       
  2758 		{
       
  2759 		// iterate through exceptions in reverse order so that removing exceptions doesn't upset the order
       
  2760 		for (TInt i = iExceptions->Count() - 1; i >= 0; --i)
       
  2761 			{
       
  2762 			const TAgnCalendarTime& KException = (*iExceptions)[i];
       
  2763 			if ( ! IsAnInstanceL(KException.LocalL()))
       
  2764 				{
       
  2765 				iExceptions->Remove(i);
       
  2766 				}
       
  2767 			}
       
  2768 		if (iExceptions->Count() == 0)
       
  2769 			{
       
  2770 			iExceptions->Close();
       
  2771 			delete iExceptions;
       
  2772 			iExceptions = NULL;
       
  2773 			}
       
  2774 		}
       
  2775 	}
       
  2776 
       
  2777 EXPORT_C TBool CAgnRptDef::FindException(const TAgnCalendarTime& aException) const
       
  2778 /** Tests whether aException is in the exceptions list.
       
  2779 
       
  2780 @internalComponent
       
  2781 @param aException The exception.
       
  2782 @return ETrue = present, otherwise EFalse. */
       
  2783 	{
       
  2784 
       
  2785 	if (iExceptions)
       
  2786 		{
       
  2787 		if (iExceptions->Find(aException) != KErrNotFound)
       
  2788 			{
       
  2789 			return ETrue;
       
  2790 			}
       
  2791 		}
       
  2792 	return EFalse;
       
  2793 	}
       
  2794 
       
  2795 EXPORT_C void CAgnRptDef::ClearTimeArray(RArray<TAgnCalendarTime>*& aTimeArray)
       
  2796 	{
       
  2797 	if (aTimeArray)
       
  2798 		{
       
  2799 		aTimeArray->Reset();
       
  2800 		delete aTimeArray;
       
  2801 		aTimeArray = NULL;
       
  2802 		}
       
  2803 	}
       
  2804 
       
  2805 EXPORT_C void CAgnRptDef::RemoveAllExceptions()
       
  2806 /** Removes all the exceptions from the exception list. 
       
  2807 
       
  2808 @internalComponent
       
  2809 */
       
  2810 	{
       
  2811 	ClearTimeArray(iExceptions);
       
  2812 	}
       
  2813 
       
  2814 void CAgnRptDef::CopyTimeArrayL(const RArray<TAgnCalendarTime>* aSource, RArray<TAgnCalendarTime>*& aDestination)
       
  2815 	{
       
  2816 	ClearTimeArray(aDestination);
       
  2817 	
       
  2818 	if (aSource)
       
  2819 		{
       
  2820 		EnsureTimeArrayExistsL(aDestination);
       
  2821 		
       
  2822 		const TInt KNumTimes = aSource->Count();
       
  2823 		for (TInt i = 0; i < KNumTimes; ++i)
       
  2824 			{
       
  2825 			TAgnCalendarTime::InsertInOrderL(*aDestination, (*aSource)[i]);
       
  2826 			}
       
  2827 		}
       
  2828 	}
       
  2829 	
       
  2830 void CAgnRptDef::EnsureTimeArrayExistsL(RArray<TAgnCalendarTime>*& aTimeArray)
       
  2831 	{
       
  2832 	if ( ! aTimeArray)
       
  2833 		{
       
  2834 		aTimeArray = new (ELeave) RArray<TAgnCalendarTime>;
       
  2835 		}
       
  2836 	}
       
  2837 	
       
  2838 EXPORT_C void CAgnRptDef::AddSporadicDateL(const TAgnCalendarTime& aSporadicDate)
       
  2839 /** Adds a sporadic date to the list of sporadic dates (first creating the sporadic date list 
       
  2840 if necessary).
       
  2841 
       
  2842 @internalComponent
       
  2843 @param aSporadicDate The sporadic date to add to the list. */
       
  2844 	{
       
  2845 	EnsureTimeArrayExistsL(iSporadicDates);
       
  2846 	TAgnCalendarTime::InsertInOrderL(*iSporadicDates, aSporadicDate);
       
  2847 	}
       
  2848 
       
  2849 TInt CAgnRptDef::FindSporadicDate(const TAgnCalendarTime& aSporadicDate) const
       
  2850 /** Tests whether aSporadicDate is in the sporadic dates list, using the sporadic date 
       
  2851 as the find key.
       
  2852 
       
  2853 @internalComponent
       
  2854 @param aSporadicDate The sporadic dates.
       
  2855 @return ETrue = present, otherwise EFalse. */
       
  2856 	{
       
  2857 	if (iSporadicDates)
       
  2858 		{
       
  2859 		return iSporadicDates->Find(aSporadicDate);
       
  2860 		}
       
  2861 	return KErrNotFound;
       
  2862 	}
       
  2863 
       
  2864 void CAgnRptDef::RemoveSporadicDate(const TAgnCalendarTime& aSporadicDate)
       
  2865 /** Removes a sporadic date from the sporadic date list. 
       
  2866 
       
  2867 If it is the last sporadic date in the list, the list is deleted.
       
  2868 
       
  2869 @internalComponent
       
  2870 @param aSporadicDate The sporadic date to be removed.
       
  2871 @return ETrue if the sporadic date was found and removed, otherwise EFalse. */
       
  2872 	{
       
  2873 
       
  2874 	if (iSporadicDates)
       
  2875 		{
       
  2876 		TInt pos = FindSporadicDate(aSporadicDate);
       
  2877 		if (pos != KErrNotFound)
       
  2878 			{
       
  2879 			iSporadicDates->Remove(pos);
       
  2880 			if (iSporadicDates->Count() == 0)
       
  2881 				{
       
  2882 				ClearTimeArray(iSporadicDates);
       
  2883 				}
       
  2884 			}
       
  2885 	   }
       
  2886 	}
       
  2887 
       
  2888 EXPORT_C void CAgnRptDef::RemoveAllSporadicDates()
       
  2889 /** Removes all the sporadic dates from the sporadic date list. 
       
  2890 
       
  2891 @internalComponent
       
  2892 */
       
  2893 	{
       
  2894 	ClearTimeArray(iSporadicDates);
       
  2895 	}
       
  2896 
       
  2897 EXPORT_C void CAgnRptDef::CopyL(const CAgnRptDef& aRptDef)
       
  2898 /** Copies the contents of a repeat definition into this object.
       
  2899 
       
  2900 @internalComponent
       
  2901 @param aRRule Pointer to the item to be copied. */
       
  2902 	{
       
  2903 	if (aRptDef.HasRepeatRule())
       
  2904 		{
       
  2905 		CreateRptObjectL(*aRptDef.iRRule);		
       
  2906 		}
       
  2907 
       
  2908 	CopyTimeArrayL(aRptDef.iExceptions, iExceptions);
       
  2909 	CopyTimeArrayL(aRptDef.iSporadicDates, iSporadicDates);
       
  2910 		
       
  2911 	if (aRptDef.iTimeZone != NULL)
       
  2912 		{
       
  2913 		if(iTimeZone == NULL)
       
  2914 			{
       
  2915 			iTimeZone = aRptDef.iTimeZone->CloneL(); 
       
  2916 			}
       
  2917 		else
       
  2918 			{
       
  2919 			iTimeZone->CopyL(*aRptDef.iTimeZone);
       
  2920 			}
       
  2921 		TimeZoneChangedL();
       
  2922 		}
       
  2923 	else
       
  2924 		{
       
  2925 		ResetTimeZone();
       
  2926 		}
       
  2927 	}
       
  2928 
       
  2929 void CAgnRptDef::ResetTimeZone()
       
  2930 	{
       
  2931 	delete iTimeZone;
       
  2932 	iTimeZone = NULL;
       
  2933 	
       
  2934 	if (iRRule)
       
  2935 		{
       
  2936 		iRRule->ResetCachedStartTimeOffset();
       
  2937 		iRRule->ResetCachedUntilTimeOffset();
       
  2938 		}
       
  2939 	}
       
  2940 
       
  2941 TBool CAgnRptDef::operator==(const CAgnRptDef& aRptDef) const
       
  2942 /** Compares two repeat definitions for equality. 
       
  2943 
       
  2944 This compares all repeat details, the repeat type and the exception list.
       
  2945 
       
  2946 @internalComponent
       
  2947 @param aRRule The repeat definition.
       
  2948 @return True if complete definitions agree, otherwise False. */
       
  2949 	{
       
  2950 
       
  2951 	if (HasRepeatRule() && !aRptDef.HasRepeatRule() || !HasRepeatRule() && aRptDef.HasRepeatRule())
       
  2952 		{
       
  2953 		return EFalse;
       
  2954 		}
       
  2955 
       
  2956 	if (aRptDef.HasRepeatRule())
       
  2957 		{
       
  2958 		if (Type() != aRptDef.Type())
       
  2959 			{
       
  2960 			return EFalse;
       
  2961 			}
       
  2962 		
       
  2963 		switch (Type())
       
  2964 			{
       
  2965 			case TAgnRpt::EDaily:
       
  2966 				{
       
  2967 				const TAgnDailyRpt* d1 = static_cast<const TAgnDailyRpt*>(RRule());
       
  2968 				const TAgnDailyRpt* d2 = static_cast<const TAgnDailyRpt*>(aRptDef.RRule());
       
  2969 				if (!(*d1 == *d2)) return EFalse;
       
  2970 				}
       
  2971 				break;
       
  2972 			case TAgnRpt::EWeekly: 
       
  2973 				{
       
  2974 				const TAgnWeeklyRpt* w1 = static_cast<const TAgnWeeklyRpt*>(RRule());
       
  2975 				const TAgnWeeklyRpt* w2 = static_cast<const TAgnWeeklyRpt*>(aRptDef.RRule());
       
  2976 				if (!(*w1 == *w2)) return EFalse;
       
  2977 				}
       
  2978 				break;
       
  2979 			case TAgnRpt::EMonthlyByDays: 
       
  2980 				{
       
  2981 				const TAgnMonthlyByDaysRpt* mp1 = static_cast<const TAgnMonthlyByDaysRpt*>(RRule());
       
  2982 				const TAgnMonthlyByDaysRpt* mp2 = static_cast<const TAgnMonthlyByDaysRpt*>(aRptDef.RRule());
       
  2983 				if (!(*mp1 == *mp2)) return EFalse;
       
  2984 				}
       
  2985 				break;
       
  2986 			case TAgnRpt::EMonthlyByDates: 
       
  2987 				{
       
  2988 				const TAgnMonthlyByDatesRpt* md1 = static_cast<const TAgnMonthlyByDatesRpt*>(RRule());
       
  2989 				const TAgnMonthlyByDatesRpt* md2 = static_cast<const TAgnMonthlyByDatesRpt*>(aRptDef.RRule());
       
  2990 				if (!(*md1 == *md2)) return EFalse;
       
  2991 				}
       
  2992 				break;
       
  2993 			case TAgnRpt::EYearlyByDay: 
       
  2994 				{
       
  2995 				const TAgnYearlyByDayRpt* yp1 = static_cast<const TAgnYearlyByDayRpt*>(RRule());
       
  2996 				const TAgnYearlyByDayRpt* yp2 = static_cast<const TAgnYearlyByDayRpt*>(aRptDef.RRule());
       
  2997 				if (!(*yp1 == *yp2)) return EFalse;
       
  2998 				}
       
  2999 				break;
       
  3000 			case TAgnRpt::EYearlyByDate: 
       
  3001 				{
       
  3002 				const TAgnYearlyByDateRpt* yd1 = static_cast<const TAgnYearlyByDateRpt*>(RRule());
       
  3003 				const TAgnYearlyByDateRpt* yd2 = static_cast<const TAgnYearlyByDateRpt*>(aRptDef.RRule());
       
  3004 				if (!(*yd1 == *yd2)) return EFalse;
       
  3005 				}
       
  3006 				break;
       
  3007 			}
       
  3008 		}
       
  3009 
       
  3010 	if ( ! TAgnCalendarTime::CompareTimeArrays(Exceptions(), aRptDef.Exceptions()) )
       
  3011 		{
       
  3012 		return EFalse;
       
  3013 		}
       
  3014 
       
  3015 	if ( ! TAgnCalendarTime::CompareTimeArrays(SporadicDateList(), aRptDef.SporadicDateList()) )
       
  3016 		{
       
  3017 		return EFalse;
       
  3018 		}
       
  3019 
       
  3020 	return ETrue;
       
  3021 	}
       
  3022 
       
  3023 TInt CAgnRptDef::InvariantL() const
       
  3024 /**
       
  3025 Check that the rpt doesn't violate its invariants
       
  3026 @internalComponent
       
  3027 */
       
  3028 	{
       
  3029 	// accept as valid if iRRule has not yet been set	
       
  3030 	if (iRRule == NULL)
       
  3031 		{
       
  3032 		return KErrNone;
       
  3033 		}
       
  3034 	
       
  3035 	if (iRRule->InvariantL()==KErrNone)
       
  3036 		{
       
  3037  		return (KErrNone);
       
  3038 		}
       
  3039 		
       
  3040 	return (EAgmErrBadRepeat);
       
  3041 	}
       
  3042 
       
  3043 
       
  3044 
       
  3045 EXPORT_C void CAgnRptDef::ExternalizeL(RWriteStream& aStream, TBool aToBuffer)
       
  3046 /** Externalises the repeat definition to a write stream.
       
  3047 
       
  3048 @internalComponent
       
  3049 @param aStream Stream to which the object should be externalised. */
       
  3050 	{
       
  3051 	__ASSERT_ALWAYS(InvariantL()==KErrNone, User::Leave(EAgmErrBadRepeat));
       
  3052 
       
  3053     // Repeat Rule
       
  3054 	if (HasRepeatRule())
       
  3055 		{
       
  3056 		aStream.WriteUint8L(ETrue);
       
  3057 		aStream.WriteUint8L(Type());
       
  3058 		aStream << *iRRule;	
       
  3059 		}
       
  3060 	else
       
  3061 		{
       
  3062 		aStream.WriteUint8L(EFalse);
       
  3063 		}	
       
  3064 
       
  3065 	// Exceptions
       
  3066 	if (iExceptions)
       
  3067 		{
       
  3068 		aStream.WriteUint8L(ETrue);
       
  3069 		TAgnCalendarTime::ExternalizeTimeArrayL(*iExceptions, aStream);
       
  3070 		}
       
  3071 	else
       
  3072 		{
       
  3073 		aStream.WriteUint8L(EFalse);
       
  3074 		}
       
  3075 	
       
  3076 	// Sporadic Dates
       
  3077 	if (iSporadicDates)
       
  3078 		{
       
  3079 		aStream.WriteUint8L(ETrue);
       
  3080 		TAgnCalendarTime::ExternalizeTimeArrayL(*iSporadicDates, aStream);
       
  3081 		}
       
  3082 	else
       
  3083 		{
       
  3084 		aStream.WriteUint8L(EFalse);
       
  3085 		}
       
  3086 		
       
  3087   	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
  3088   		{// no timezone rule for floating time mode
       
  3089 	   	aStream.WriteUint8L(EFalse);
       
  3090   		}
       
  3091   	else
       
  3092   		{
       
  3093 	  	if (iTimeZone == NULL)
       
  3094 	  		{	// Set time Zone for fixed time mode
       
  3095 	  		SetTimeZoneL();
       
  3096 	  		}
       
  3097 
       
  3098 	   	aStream.WriteUint8L(ETrue);
       
  3099 	   	if(aToBuffer)
       
  3100 	   		{
       
  3101 	   		iTimeZone->WriteToBufferL(aStream);
       
  3102 	   		}
       
  3103 	   	else
       
  3104 	   		{
       
  3105 	   		iTimeZone->ExternalizeL(aStream);
       
  3106 	   		}
       
  3107   		}
       
  3108 	}
       
  3109 				
       
  3110 void CAgnRptDef::InternalizeRepeatRuleL(RReadStream& aStream)
       
  3111 	{
       
  3112 	TBool hasRepeatRule = aStream.ReadUint8L();
       
  3113 	
       
  3114 	// Repeat Rule
       
  3115 	if (hasRepeatRule)
       
  3116 		{
       
  3117 		TAgnRpt::TType type = static_cast<TAgnRpt::TType>(aStream.ReadUint8L());
       
  3118 	
       
  3119 		if (type < TAgnRpt::EDaily || type > TAgnRpt::EYearlyByDay)
       
  3120 			{
       
  3121 			User::Leave(KErrCorrupt);
       
  3122 			}
       
  3123 
       
  3124 		CreateRptObjectL(type);
       
  3125 		aStream >> *iRRule;
       
  3126 		}
       
  3127 	}
       
  3128 
       
  3129 void CAgnRptDef::InternalizeExceptionsL(RReadStream& aStream)
       
  3130 	{
       
  3131 	ClearTimeArray(iExceptions);
       
  3132 	
       
  3133 	if (aStream.ReadUint8L())
       
  3134 		{
       
  3135 		EnsureTimeArrayExistsL(iExceptions);
       
  3136 		TAgnCalendarTime::InternalizeTimeArrayL(*iExceptions, aStream);
       
  3137 		}
       
  3138 	}
       
  3139 
       
  3140 void CAgnRptDef::InternalizeSporadicDatesL(RReadStream& aStream)
       
  3141 	{
       
  3142 	ClearTimeArray(iSporadicDates);
       
  3143 
       
  3144 	if (aStream.ReadUint8L())
       
  3145 		{
       
  3146 		EnsureTimeArrayExistsL(iSporadicDates);
       
  3147 		TAgnCalendarTime::InternalizeTimeArrayL(*iSporadicDates, aStream);
       
  3148 		}
       
  3149 	}
       
  3150 
       
  3151 void CAgnRptDef::InternalizeTimeZoneL(RReadStream& aStream, TBool aFromBuffer)
       
  3152 	{
       
  3153 	// Time Zone
       
  3154 	TBool hasTimeZone = aStream.ReadUint8L();
       
  3155 	ResetTimeZone();
       
  3156 	
       
  3157 	if(hasTimeZone)
       
  3158 		{
       
  3159 		iTimeZone = CAgnTzRules::NewL(aStream, aFromBuffer);
       
  3160 		TimeZoneChangedL();
       
  3161 		}
       
  3162 	}
       
  3163 
       
  3164 EXPORT_C void CAgnRptDef::InternalizeL(RReadStream& aStream, TBool aFromBuffer)
       
  3165 /** Internalises the repeat definition from a read stream, including type, repeat 
       
  3166 details and exception list.
       
  3167 
       
  3168 @internalComponent
       
  3169 @param aStream Stream from which the object should be internalised. */
       
  3170 	{
       
  3171     InternalizeRepeatRuleL(aStream);
       
  3172     InternalizeExceptionsL(aStream);
       
  3173     InternalizeSporadicDatesL(aStream);
       
  3174     InternalizeTimeZoneL(aStream, aFromBuffer);	
       
  3175   	  	  
       
  3176 	__ASSERT_ALWAYS(InvariantL()==KErrNone, User::Leave(KErrCorrupt));
       
  3177 	}
       
  3178 
       
  3179 
       
  3180 EXPORT_C TUint CAgnRptDef::InstanceCountL() const
       
  3181 /** Gets the number of repeat instances generated by the repeat algorithm, including 
       
  3182 excepted instances.
       
  3183 
       
  3184 @internalComponent
       
  3185 @return The number of repeat instances. */
       
  3186 	{
       
  3187 	TInt total((0));
       
  3188 	
       
  3189 	if (HasRepeatRule())
       
  3190 		{
       
  3191 		total = iRRule->InstanceCountL();
       
  3192 		}
       
  3193 	else
       
  3194 		{
       
  3195 		total = 1;//count DtStart if there is no Repeat Rule
       
  3196 		}
       
  3197 		
       
  3198 	if (HasSporadicDates())
       
  3199 		{
       
  3200 		total = total + iSporadicDates->Count();
       
  3201 		}
       
  3202 	
       
  3203 	return total;
       
  3204 	}
       
  3205 
       
  3206 
       
  3207 EXPORT_C TBool CAgnRptDef::IsAnUnexceptedInstanceL(const TTime& aDate) const
       
  3208 /** Tests whether aDate falls on an instance generated from the repeat algorithm or a sporadic date
       
  3209 which is not excepted.
       
  3210 
       
  3211 @internalComponent
       
  3212 @param aDate The system local date to be checked, expressed as Current System Local Time
       
  3213 @return True = the date falls on a non excepted instance, otherwise False. */
       
  3214 	{
       
  3215 	// IsAnInstanceL() is exported, so it takes System Local Times.
       
  3216 	if (!IsAnInstanceL(aDate))
       
  3217 		{
       
  3218 		return EFalse;
       
  3219 		}
       
  3220 	// FindException() is exported, so it takes System Local Times.//	
       
  3221 	TAgnCalendarTime exceptionToFind;
       
  3222 	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
  3223 		{
       
  3224 		exceptionToFind.SetFloatingL(aDate);
       
  3225 		}
       
  3226 	else
       
  3227 		{
       
  3228 		exceptionToFind.SetLocalL(aDate);
       
  3229 		}
       
  3230 	if (FindException(exceptionToFind))  
       
  3231 		{
       
  3232 		return EFalse;
       
  3233 		}
       
  3234 
       
  3235 	return ETrue;
       
  3236 	}
       
  3237 
       
  3238 
       
  3239 EXPORT_C TBool CAgnRptDef::IsAnInstanceL(const TTime& aDate) const
       
  3240 /** Tests whether aDate (System local time) falls on an instance generated from the repeat algorithm or on a sporadic date 
       
  3241 including excepted items. 
       
  3242 
       
  3243 Note: this function is not intended to be called by a view.
       
  3244 
       
  3245 @internalComponent
       
  3246 @param aDate The date to be checked, expressed as System Local Time
       
  3247 @return True = date falls on an instance, otherwise False. */
       
  3248 	{
       
  3249 	return IsASporadicDateInstanceL(aDate) || IsARepeatRuleDateInstanceL(aDate) || (aDate == StartTime().LocalL());
       
  3250 	}
       
  3251 
       
  3252 EXPORT_C TBool CAgnRptDef::NudgeNextInstanceL(const TTime& aLocalDate, TTime& aLocalNext, TBool aCheckUnexcepted) const
       
  3253 /** Tests whether there is another repeat instance date after aDate (System local time), including excepted 
       
  3254 instances and Sporadic Dates. 
       
  3255 
       
  3256 If there is, it returns ETrue and sets aNext to it. If not, it returns 
       
  3257 EFalse and sets aNext to the last valid instance date. If aDate is a valid 
       
  3258 instance, then aNext is set to it, not the next instance.
       
  3259 
       
  3260 For example:
       
  3261 
       
  3262 If repeat instances fall on 10th Jan and 20th Jan, then if aDate = 10th Jan, 
       
  3263 this function returns ETrue and sets aNext to 10th Jan. If aDate = 11th to 19th Jan, 
       
  3264 it  returns ETrue and sets aNext to 20th Jan. If aDate = 21st Jan, it returns EFalse 
       
  3265 and sets aNext to 20th Jan.
       
  3266 
       
  3267 This function can leave.
       
  3268 
       
  3269 @internalComponent
       
  3270 @param aDate The date, expressed as System Local Time
       
  3271 @param aNext On return contains the date (in System Local Time) of the next instance if there is one, 
       
  3272 or if not, the last valid instance date
       
  3273 @return True if there is a next instance, otherwise False. */
       
  3274     {
       
  3275 	TTime utcDate = AgnDateTime::ConvertToUtcTimeL(aLocalDate) + TTimeIntervalMicroSeconds(1);
       
  3276 
       
  3277 	TBool retVal = NudgeInstanceForwardsUtcL(utcDate, aLocalNext, aCheckUnexcepted);
       
  3278 
       
  3279 	if (retVal)
       
  3280 		{			
       
  3281 		aLocalNext = AgnDateTime::ConvertToLocalTimeL(aLocalNext);	
       
  3282 		}
       
  3283 	
       
  3284 	return retVal;
       
  3285 	}
       
  3286 
       
  3287 TBool CAgnRptDef::NudgeInstanceForwardsUtcL(const TTime& aUtcDate, TTime& aUtcNext, TBool aCheckExcepted) const 
       
  3288 	{
       
  3289 	TBool retValue((EFalse));
       
  3290 	
       
  3291 	// If there is a Rpt Rule and No Sporadic Dates
       
  3292 	if (iRRule && !HasSporadicDates())
       
  3293 		{
       
  3294 		retValue = NudgeNextRepeatInstanceUtcL(aUtcDate, aUtcNext, aCheckExcepted);
       
  3295 		}
       
  3296 	// else if there are Sporadic Dates and no Rpt Rule	
       
  3297 	else if (!iRRule && HasSporadicDates())	
       
  3298 		{
       
  3299 		retValue = NudgeNextSporadicInstanceUtcL(aUtcDate, aUtcNext, aCheckExcepted);
       
  3300 		const TAgnCalendarTime& KFirstInstanceUtc = StartTime();
       
  3301 		if (aUtcDate <= KFirstInstanceUtc.UtcL() && 
       
  3302 			(KFirstInstanceUtc.UtcL() < aUtcNext || retValue == EFalse))
       
  3303 			{
       
  3304 			if ( ! FindException(KFirstInstanceUtc))
       
  3305 				{
       
  3306 				aUtcNext = KFirstInstanceUtc.UtcL();
       
  3307 				retValue = ETrue;
       
  3308 				}
       
  3309 			}
       
  3310 		}
       
  3311 	else if (iRRule && HasSporadicDates()) // there are both Sporadic Dates and a Rule	
       
  3312 		{
       
  3313 		TTime rptNext;
       
  3314 		TBool rptHasNext = NudgeNextRepeatInstanceUtcL(aUtcDate, rptNext, aCheckExcepted);
       
  3315 	
       
  3316 		TTime sporadicNext;
       
  3317 		TBool sporadicHasNext = NudgeNextSporadicInstanceUtcL(aUtcDate, sporadicNext, aCheckExcepted);
       
  3318 			
       
  3319 		if (sporadicHasNext && !rptHasNext)
       
  3320 			{
       
  3321 			aUtcNext = sporadicNext;
       
  3322 			retValue = ETrue;
       
  3323 			}
       
  3324 		else if (!sporadicHasNext && rptHasNext)
       
  3325 			{
       
  3326 			aUtcNext = rptNext;
       
  3327 			retValue = ETrue;
       
  3328 			}
       
  3329 		else if (sporadicHasNext && rptHasNext) //  both have a next instance. Return the valid date closest to aDate 
       
  3330 			{
       
  3331 			aUtcNext = sporadicNext < rptNext ? sporadicNext : rptNext; 
       
  3332 			retValue = ETrue;
       
  3333 			}
       
  3334 		else  // neither has a next instance return EFalse  
       
  3335 			{			 
       
  3336 			retValue = EFalse;			
       
  3337 			}		
       
  3338 		}		
       
  3339 	return retValue;				
       
  3340 	}
       
  3341 
       
  3342 
       
  3343 TBool CAgnRptDef::NudgeNextRepeatInstanceUtcL(const TTime& aUtcDate, TTime& aUtcNext, TBool aConsiderExceptions) const
       
  3344 	{
       
  3345 	if (aUtcDate > iRRule->UntilTimeL().UtcL())
       
  3346 		{
       
  3347 		return (EFalse);
       
  3348 		}
       
  3349 		
       
  3350 	return aConsiderExceptions ? NudgeNextUnexceptedRepeatInstanceUtcL(aUtcDate, aUtcNext) : NudgeNextRepeatInstanceToNextValidInstanceUtcL(aUtcDate, aUtcNext);		
       
  3351 	}
       
  3352 
       
  3353 
       
  3354 TBool CAgnRptDef::NudgeNextRepeatInstanceToNextValidInstanceUtcL(const TTime& aUtcDate, TTime& aUtcNext) const
       
  3355 	{
       
  3356 	if (aUtcDate < StartTime().UtcL())
       
  3357 		{
       
  3358 		aUtcNext = iRRule->NudgeNextInstanceUtcL(StartTime().UtcL());	
       
  3359 		}
       
  3360 	else
       
  3361 		{
       
  3362 		aUtcNext = iRRule->NudgeNextInstanceUtcL(aUtcDate);	
       
  3363 		}	
       
  3364 	
       
  3365 	// if this is a valid instance that is the same as the one passed to the repeat rule's nudge
       
  3366 	if (aUtcNext != Time::NullTTime() && aUtcNext < aUtcDate)
       
  3367 		{
       
  3368 		return EFalse;
       
  3369 		}
       
  3370 
       
  3371 	return aUtcNext != Time::NullTTime() && aUtcNext <= iRRule->UntilTimeL().UtcL() && aUtcNext >= StartTime().UtcL();		
       
  3372 	}
       
  3373 
       
  3374 
       
  3375 TBool CAgnRptDef::NudgePreviousRepeatInstanceToPreviousValidInstanceUtcL(const TTime& aUtcDate, TTime& aUtcPrev) const
       
  3376 	{
       
  3377 	TTime dateUtc = aUtcDate;
       
  3378 	if (aUtcDate > iRRule->UntilTimeL().UtcL())
       
  3379 		{
       
  3380 		dateUtc = iRRule->UntilTimeL().UtcL();
       
  3381 		}
       
  3382 		
       
  3383 	aUtcPrev = iRRule->NudgePreviousInstanceUtcL(dateUtc);		
       
  3384 
       
  3385 	// if this is a valid instance, check that this is previous (time-wise)
       
  3386 	if (aUtcPrev != Time::NullTTime() && aUtcPrev > aUtcDate)   
       
  3387 		{
       
  3388 		return EFalse;
       
  3389 		}	
       
  3390 				
       
  3391 	return aUtcPrev != Time::NullTTime() && aUtcPrev <= iRRule->UntilTimeL().UtcL() && aUtcPrev >= StartTime().UtcL();		
       
  3392 	}
       
  3393 
       
  3394 TBool CAgnRptDef::NudgeNextUnexceptedRepeatInstanceUtcL(const TTime& aUtcDate, TTime& aUtcNext) const
       
  3395 	{
       
  3396 	TTime currentDate = aUtcDate;
       
  3397 	if (currentDate < StartTime().UtcL())
       
  3398 		{
       
  3399 		currentDate = StartTime().UtcL();
       
  3400 		}
       
  3401 
       
  3402 	TTime tmpLocalTime;	
       
  3403 	TTime next = aUtcNext;
       
  3404 	FOREVER
       
  3405 		{
       
  3406 		if (!NudgeNextRepeatInstanceToNextValidInstanceUtcL(currentDate, next))
       
  3407 			{
       
  3408 			return EFalse;
       
  3409 			}
       
  3410 
       
  3411 		TAgnCalendarTime candidateException;
       
  3412 		if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
  3413 			{
       
  3414 			candidateException.SetFloatingL(AgnDateTime::ConvertToLocalTimeL(next));
       
  3415 			}
       
  3416 		else
       
  3417 			{
       
  3418 			candidateException.SetUtcL(next);
       
  3419 			}
       
  3420 		if (FindException(candidateException))
       
  3421 			{
       
  3422 			tmpLocalTime = AgnDateTime::ConvertToLocalTimeL(currentDate);
       
  3423 			tmpLocalTime += static_cast<TTimeIntervalDays>(1);
       
  3424 			currentDate = AgnDateTime::ConvertToUtcTimeL(tmpLocalTime);
       
  3425 			}
       
  3426 		else
       
  3427 			{
       
  3428 			aUtcNext = next;
       
  3429 			return ETrue;
       
  3430 			}
       
  3431 		}	
       
  3432 	}
       
  3433 	    
       
  3434 
       
  3435 // aCheckExcepted indicates that sporadic dates that have exceptions are not to be considered as candidates
       
  3436 TBool CAgnRptDef::NudgeNextSporadicInstanceUtcL(const TTime& aUtcDate, TTime& aUtcNext, TBool aCheckExcepted) const
       
  3437 	{
       
  3438 	TAgnCalendarTime utcDate;
       
  3439 	utcDate.SetUtcL(aUtcDate);
       
  3440 	TBool retVal((EFalse));
       
  3441 	TBool moreCandidates((ETrue));
       
  3442 	TInt bestMatchPos((KErrNotFound));			
       
  3443 	TInt pos((iSporadicDates->Count() - 1));
       
  3444 		
       
  3445 	while (moreCandidates && pos >= 0)
       
  3446 		{
       
  3447 		// if the date is less than the sporadic array[pos] date
       
  3448 		moreCandidates = (utcDate <= (*iSporadicDates)[pos--]);
       
  3449 			
       
  3450 		// if the sporadic array[pos] date is later than the KDate and if we are checking exceptions it is not excepted
       
  3451 		const TAgnCalendarTime& KExceptionToFind = (*iSporadicDates)[pos + 1];
       
  3452 		if (moreCandidates && !(aCheckExcepted && FindException(KExceptionToFind)))
       
  3453 			{
       
  3454 			bestMatchPos = pos + 1;
       
  3455 			}	
       
  3456 		}
       
  3457 	
       
  3458     if (bestMatchPos != KErrNotFound)
       
  3459         {
       
  3460         retVal = ETrue; 
       
  3461         aUtcNext = (*iSporadicDates)[bestMatchPos].UtcL();
       
  3462         }
       
  3463     
       
  3464 	return retVal;
       
  3465 	}
       
  3466 
       
  3467 
       
  3468 EXPORT_C TBool CAgnRptDef::NudgePreviousUnexceptedInstanceL(const TTime& aLocalDate, TTime& aLocalPrev) const
       
  3469 /** Tests whether there is a repeat instance or sporadic date before aDate. 
       
  3470 
       
  3471 If there is, it returns ETrue and sets aNext to it. If not, it returns EFalse 
       
  3472 and sets aNext to the last valid instance date. If aDate is a valid instance, 
       
  3473 then aNext is set to it, not the next instance.
       
  3474 
       
  3475 This function can leave.
       
  3476 
       
  3477 For example:
       
  3478 
       
  3479 If repeat instances fall on 10th Jan and 20th Jan, then if aDate = 20th Jan, 
       
  3480 it returns ETrue and sets aNext to 20th Jan. If aDate = 11th to 19th Jan, it 
       
  3481 returns ETrue and sets aNext to 10th Jan. If aDate = 9th Jan, it returns EFalse 
       
  3482 and sets aNext to 10th Jan.
       
  3483 
       
  3484 @internalComponent
       
  3485 @param aDate The date (System Local Time).
       
  3486 @param aPrev On return contains the date (System Local Time) of the previous instance if there 
       
  3487 is one, otherwise the first valid instance date.
       
  3488 @return True if there is a previous instance, otherwise false. */
       
  3489 	{
       
  3490 	TTime utcDate = AgnDateTime::ConvertToUtcTimeL(aLocalDate) - TTimeIntervalMicroSeconds(1);
       
  3491 
       
  3492 	TBool retVal = NudgeInstanceBackwardsUtcL(utcDate, aLocalPrev, ETrue);
       
  3493 	
       
  3494 	if (retVal)
       
  3495 		{
       
  3496 		aLocalPrev = AgnDateTime::ConvertToLocalTimeL(aLocalPrev);	
       
  3497 		}
       
  3498 	
       
  3499 	return retVal;	  
       
  3500 	}
       
  3501 
       
  3502 
       
  3503 TBool CAgnRptDef::NudgeInstanceBackwardsUtcL(const TTime& aUtcDate, TTime& aUtcPrev, TBool aCheckExcepted) const
       
  3504 	{
       
  3505 	TBool retValue((EFalse));
       
  3506 	// If there is a Rpt Rule and No Sporadic Dates
       
  3507 	if (iRRule && !HasSporadicDates())
       
  3508 		{
       
  3509 		retValue = NudgePreviousRepeatInstanceUtcL(aUtcDate, aUtcPrev, aCheckExcepted);
       
  3510 		}
       
  3511 	// else if there are Sporadic Dates and no Rpt Rule	
       
  3512 	else if (!iRRule && HasSporadicDates())	
       
  3513 		{
       
  3514 		retValue = NudgePreviousSporadicInstanceUtcL(aUtcDate, aUtcPrev, aCheckExcepted);
       
  3515 		const TAgnCalendarTime& KFirstInstanceUtc = StartTime();
       
  3516 		if (aUtcDate >= KFirstInstanceUtc.UtcL() && 
       
  3517 			(KFirstInstanceUtc.UtcL() > aUtcPrev || retValue == EFalse))
       
  3518 			{
       
  3519 			if (! FindException(KFirstInstanceUtc))
       
  3520 				{
       
  3521 				aUtcPrev = KFirstInstanceUtc.UtcL();
       
  3522 				retValue = ETrue;
       
  3523 				}
       
  3524 			}
       
  3525 		}
       
  3526 	else if (iRRule && HasSporadicDates())
       
  3527 		{
       
  3528 		// there are both Sporadic Dates and a Rule	
       
  3529 		TTime rptPrevUtc;
       
  3530 		TBool rptHasPrev = NudgePreviousRepeatInstanceUtcL(aUtcDate, rptPrevUtc, aCheckExcepted);
       
  3531 	
       
  3532 		TTime sporadicPrevUtc;
       
  3533 		TBool sporadicHasPrev = NudgePreviousSporadicInstanceUtcL(aUtcDate, sporadicPrevUtc, aCheckExcepted);
       
  3534 			
       
  3535 		if (sporadicHasPrev && !rptHasPrev)
       
  3536 			{
       
  3537 			aUtcPrev = sporadicPrevUtc;
       
  3538 			retValue = ETrue;
       
  3539 			}
       
  3540 		else if (!sporadicHasPrev && rptHasPrev)
       
  3541 			{
       
  3542 			aUtcPrev = rptPrevUtc;
       
  3543 			retValue = ETrue;
       
  3544 			}
       
  3545 		else if (sporadicHasPrev && rptHasPrev)	  //  both have a next instance. Return the valid date closest to aDate 
       
  3546 			{
       
  3547 			aUtcPrev = sporadicPrevUtc > rptPrevUtc ? sporadicPrevUtc : rptPrevUtc;
       
  3548 			retValue = ETrue; 
       
  3549 			}
       
  3550 		else   //  neither have a next instance (under some circumstances repeat rules do not produce aNext.  
       
  3551 		       // It is beleived that this is not used by the caller if this function returns EFalse
       
  3552 			{
       
  3553 			retValue = EFalse;
       
  3554 			}			
       
  3555 		}
       
  3556 	return retValue;	
       
  3557 	} 
       
  3558 
       
  3559 TBool CAgnRptDef::NudgePreviousSporadicInstanceUtcL(const TTime& aUtcDate, TTime& aUtcPrev, TBool aCheckExcepted) const
       
  3560 	{
       
  3561 	TAgnCalendarTime utcTime;
       
  3562 	utcTime.SetUtcL(aUtcDate);
       
  3563 	const TInt KCount = iSporadicDates->Count();
       
  3564 	TBool retVal((EFalse));
       
  3565 	TBool moreCandidates((ETrue));
       
  3566 	TInt bestMatchPos((KErrNotFound));			
       
  3567 	TInt pos((0));
       
  3568 		
       
  3569 	while (moreCandidates && KCount > pos)
       
  3570 		{
       
  3571 		// if the date is more than the sporadic array[pos] date
       
  3572 		moreCandidates = (utcTime >= (*iSporadicDates)[pos++]);  
       
  3573 			
       
  3574 		// if the sporadic array[pos] date is less than the KDate and if we are checking exceptions and it is not excepted
       
  3575 		const TAgnCalendarTime& KExceptionToFind = (*iSporadicDates)[pos - 1];
       
  3576 		if (moreCandidates && !(aCheckExcepted && FindException(KExceptionToFind)))
       
  3577 			{
       
  3578 			bestMatchPos = pos - 1;
       
  3579 			}	
       
  3580 		}
       
  3581 	
       
  3582     if (bestMatchPos != KErrNotFound)
       
  3583         {
       
  3584         retVal = ETrue;
       
  3585         aUtcPrev = (*iSporadicDates)[bestMatchPos].UtcL();
       
  3586         }
       
  3587        
       
  3588 	return retVal;		
       
  3589 	}
       
  3590 		  
       
  3591 		  
       
  3592 TBool CAgnRptDef::NudgePreviousRepeatInstanceUtcL(const TTime& aUtcDate, TTime& aUtcPrev, TBool aCheckExcepted) const
       
  3593 	{
       
  3594 	if (aUtcDate < StartTime().UtcL())
       
  3595 		{
       
  3596 		return EFalse;
       
  3597 		}
       
  3598 		
       
  3599 	return aCheckExcepted ? NudgePreviousUnexceptedRepeatInstanceUtcL(aUtcDate, aUtcPrev) : NudgePreviousRepeatInstanceToPreviousValidInstanceUtcL(aUtcDate, aUtcPrev);		
       
  3600 	}
       
  3601 
       
  3602 
       
  3603 TBool CAgnRptDef::NudgePreviousUnexceptedRepeatInstanceUtcL(const TTime& aUtcDate, TTime& aUtcPrev) const 
       
  3604 	{
       
  3605 	TTime fromUtc = aUtcDate;
       
  3606 	TTime prev = aUtcPrev;
       
  3607 	if (fromUtc > iRRule->UntilTimeL().UtcL())
       
  3608 		{
       
  3609 		fromUtc = iRRule->UntilTimeL().UtcL();
       
  3610 		}
       
  3611 	TTime tmpLocalTime;
       
  3612 	FOREVER
       
  3613 		{
       
  3614 		if (!NudgePreviousRepeatInstanceToPreviousValidInstanceUtcL(fromUtc, prev))
       
  3615 			{
       
  3616 			return EFalse;
       
  3617 			}
       
  3618 			
       
  3619 		TAgnCalendarTime candidateException;
       
  3620 		if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
  3621 			{
       
  3622 			candidateException.SetFloatingL(AgnDateTime::ConvertToLocalTimeL(prev));
       
  3623 			}
       
  3624 		else
       
  3625 			{
       
  3626 			candidateException.SetUtcL(prev);	
       
  3627 			}
       
  3628 		if ( ! FindException(candidateException))
       
  3629 			{
       
  3630 			aUtcPrev = prev;
       
  3631 			return ETrue;
       
  3632 			}
       
  3633 		else
       
  3634 			{
       
  3635 			tmpLocalTime = AgnDateTime::ConvertToLocalTimeL(fromUtc);
       
  3636 			tmpLocalTime -= static_cast<TTimeIntervalDays>(1);
       
  3637 			fromUtc = AgnDateTime::ConvertToUtcTimeL(tmpLocalTime);
       
  3638 			}
       
  3639 		}		 
       
  3640 	}
       
  3641 
       
  3642 EXPORT_C TBool CAgnRptDef::NudgeNextInstanceUtcL(const TTime& aDayUtc, TTime& aNextUtc) const
       
  3643 /**
       
  3644 @internalComponent
       
  3645 */
       
  3646 	{
       
  3647 	TTime utcNext;
       
  3648 	TBool retVal = NudgeInstanceForwardsUtcL(aDayUtc, utcNext, EFalse);
       
  3649 	if (retVal)
       
  3650 		{
       
  3651 		aNextUtc = utcNext;
       
  3652 		}
       
  3653 	return retVal;	
       
  3654 	}
       
  3655 
       
  3656 EXPORT_C TBool CAgnRptDef::NudgePreviousInstanceUtcL(const TTime& aDayUtc, TTime& aPrevUtc) const
       
  3657 /**
       
  3658 @internalComponent
       
  3659 */
       
  3660     {
       
  3661 	TTime utcPrev;
       
  3662 	TBool retVal = NudgeInstanceBackwardsUtcL(aDayUtc, utcPrev, EFalse);
       
  3663 	if (retVal)
       
  3664 		{
       
  3665 		aPrevUtc = utcPrev;
       
  3666 		}
       
  3667 	return retVal;	
       
  3668 	}
       
  3669 
       
  3670 CAgnTlsProxy* CAgnRptDef::TimeZoneAccessor()
       
  3671 	{
       
  3672 	// The client session for the agenda server creates and stores the time
       
  3673 	// zone accessor (which contains a session to the TZ server) in TLS. As
       
  3674 	// long as this is called from the same trhead that created the session
       
  3675 	// we can use the TZ server contained in the TZ accessor stored in TLS.
       
  3676 	CAgnTlsProxy* timeZoneAccessor = static_cast<CAgnTlsProxy*>(Dll::Tls());
       
  3677 	return timeZoneAccessor;
       
  3678 	}
       
  3679 
       
  3680 EXPORT_C void CAgnRptDef::SetTimeZoneL(const CTzRules& aTimeZone)
       
  3681 /** Sets the time zone to aTimeZone
       
  3682 
       
  3683 @internalComponent
       
  3684 @param aTimeZone The time zone in which the repeat entry times are expressed. It contains a 
       
  3685 collection of time zone rules. */
       
  3686 	{
       
  3687 	__ASSERT_DEBUG(TimeMode() != MAgnCalendarTimeMode::EFloating, User::Leave(KErrNotSupported));
       
  3688 	ResetTimeZone();
       
  3689 	iTimeZone = CAgnTzRules::NewL(aTimeZone);
       
  3690   	TimeZoneChangedL();
       
  3691 	}
       
  3692 
       
  3693 /** 
       
  3694 * Sets the time zone to the current system time zone. Leaves with KErrGeneral
       
  3695 * if the time zone server could not be accessed. 
       
  3696 */
       
  3697 EXPORT_C void CAgnRptDef::SetTimeZoneL()
       
  3698 /**
       
  3699 @internalComponent
       
  3700 */
       
  3701 	{
       
  3702 	__ASSERT_DEBUG(TimeMode() != MAgnCalendarTimeMode::EFloating, User::Leave(KErrNotSupported));
       
  3703 	ResetTimeZone();
       
  3704 	iTimeZone = CAgnTzRules::NewL();
       
  3705   	TimeZoneChangedL();
       
  3706 	}
       
  3707 
       
  3708 void CAgnRptDef::TimeZoneChangedL()
       
  3709 	{
       
  3710 	if (iRRule)
       
  3711 		{
       
  3712 		iRRule->ResetCachedStartTimeOffset();
       
  3713 		iRRule->ResetCachedUntilTimeOffset();
       
  3714 		}
       
  3715  	}
       
  3716  
       
  3717 EXPORT_C CTzRules* CAgnRptDef::CloneTzRulesL()
       
  3718 /** Gets a copy of the time zone rules that apply to the repeat definition.
       
  3719 
       
  3720 @internalComponent
       
  3721 */
       
  3722 	{
       
  3723 	if (iTimeZone)
       
  3724 		{
       
  3725 		return iTimeZone->CloneTzRulesL();	
       
  3726 		}
       
  3727 	return NULL;
       
  3728 	}
       
  3729 
       
  3730 TBool CAgnRptDef::IsARepeatRuleDateInstanceL(const TTime& aLocalDate) const
       
  3731 	{
       
  3732 	if (!HasRepeatRule())
       
  3733 		{
       
  3734 		return EFalse;
       
  3735 		}	
       
  3736 	
       
  3737 	if (aLocalDate < StartTime().LocalL() || aLocalDate > iRRule->UntilTimeL().LocalL())
       
  3738 		{ 
       
  3739 		return EFalse;	
       
  3740 		}	
       
  3741 	
       
  3742 			
       
  3743 	// convert aDate to UTC before passing it TAgnRpt::IsAlignedUtcL()
       
  3744 	TTime utcDate = AgnDateTime::ConvertToUtcTimeL(aLocalDate);
       
  3745 	return iRRule->IsAlignedUtcL(utcDate);	
       
  3746 	}
       
  3747 
       
  3748 
       
  3749 EXPORT_C TAgnRpt::TType CAgnRptDef::Type() const
       
  3750 /** Gets the repeat definition's type, as set by SetDaily(), SetWeekly() etc.
       
  3751 
       
  3752 @internalComponent
       
  3753 @return The repeat definition's type. */
       
  3754 	{
       
  3755 	if (iRRule)
       
  3756 		{
       
  3757 		return iRRule->Type(); 	
       
  3758 		}
       
  3759 	return TAgnRpt::EDaily;
       
  3760 	}
       
  3761 
       
  3762 TBool CAgnRptDef::IsASporadicDateInstanceL(const TTime& aLocalDate) const
       
  3763 	{
       
  3764 	if (!HasSporadicDates())
       
  3765 		{
       
  3766 		return EFalse;
       
  3767 		}
       
  3768 	
       
  3769 	TAgnCalendarTime instanceDate;
       
  3770 	if (TimeMode() == MAgnCalendarTimeMode::EFloating)
       
  3771 		{
       
  3772 		instanceDate.SetFloatingL(aLocalDate);
       
  3773 		}
       
  3774 	else
       
  3775 		{
       
  3776 		instanceDate.SetLocalL(aLocalDate);
       
  3777 		}
       
  3778 	return (FindSporadicDate(instanceDate) != KErrNotFound);	
       
  3779 	}
       
  3780 	
       
  3781 /** Returns ETrue if there is at least one sporadic date
       
  3782 
       
  3783 @internalComponent
       
  3784 @return if there is at least one sporadic date  */		
       
  3785 TBool CAgnRptDef::HasSporadicDates() const
       
  3786 	{
       
  3787 	return (iSporadicDates && iSporadicDates->Count() != 0);
       
  3788 	}	
       
  3789 
       
  3790 /** Returns ETrue if there is a repeat rule
       
  3791 
       
  3792 @internalComponent
       
  3793 @return if there is a repeat rule  */
       
  3794 TBool CAgnRptDef::HasRepeatRule() const
       
  3795 	{
       
  3796 	return (iRRule != NULL);
       
  3797 	}
       
  3798 
       
  3799 /** Clear the Repeat Rule only, leaving sporadic dates and exception dates intact
       
  3800 @internalComponent
       
  3801 */
       
  3802 void CAgnRptDef::ClearRRule()
       
  3803 	{
       
  3804 	delete iRRule;
       
  3805 	iRRule = NULL;
       
  3806 	}
       
  3807 
       
  3808 void CAgnRptDef::StartTimeChanged()
       
  3809 	{
       
  3810 	if (iRRule)
       
  3811 		{
       
  3812 		iRRule->ResetCachedStartTimeOffset();
       
  3813 		}
       
  3814 	}
       
  3815 
       
  3816 const CTzRules* CAgnRptDef::TzRules() const
       
  3817 	{
       
  3818 	if(iTimeZone)
       
  3819 		{
       
  3820 		return iTimeZone->TzRules();
       
  3821 		}
       
  3822 	
       
  3823 	return NULL; 
       
  3824 	}
       
  3825 
       
  3826 EXPORT_C TTime CAgnRptDef::ConvertFromRepeatLocalToUtcL(const TTime& aRptLocalDate) const
       
  3827 	{
       
  3828 	if (TimeMode() != MAgnCalendarTimeMode::EFloating && TzRules())
       
  3829 		{
       
  3830 		TTime utcDate = aRptLocalDate;
       
  3831 		TzRules()->ConvertToUtcL(utcDate);
       
  3832 		return utcDate;
       
  3833 		}
       
  3834 
       
  3835 	return AgnDateTime::ConvertToUtcTimeL(aRptLocalDate);
       
  3836 	}
       
  3837 
       
  3838 EXPORT_C TTime CAgnRptDef::ConvertFromUtcToRepeatLocalL(const TTime& aUtcDate) const
       
  3839 	{
       
  3840 	if (TimeMode() != MAgnCalendarTimeMode::EFloating && TzRules())
       
  3841 		{
       
  3842 		TTime rptLocalDate = aUtcDate;
       
  3843 		TzRules()->ConvertToLocalL(rptLocalDate);
       
  3844 		return rptLocalDate;
       
  3845 		}
       
  3846 
       
  3847 	return AgnDateTime::ConvertToLocalTimeL(aUtcDate);
       
  3848 	}
       
  3849 
       
  3850 MAgnCalendarTimeMode::TTimeMode CAgnRptDef::TimeMode() const
       
  3851 	{
       
  3852 	return iOwningEntry.TimeMode();
       
  3853 	}
       
  3854 
       
  3855 EXPORT_C const TAgnRpt* CAgnRptDef::RRule() const 
       
  3856 /** Gets a pointer to the repeat details.
       
  3857 @return Pointer to the repeat details
       
  3858 @internalComponent
       
  3859 */
       
  3860 	{
       
  3861 	return iRRule;
       
  3862 	}
       
  3863 
       
  3864 EXPORT_C const RArray<TAgnCalendarTime>* CAgnRptDef::Exceptions() const
       
  3865 /** Gets a pointer to the repeat definition's exception list.
       
  3866 @return Pointer to the exception list.
       
  3867 @internalComponent
       
  3868 */
       
  3869 	{
       
  3870 	return iExceptions;
       
  3871 	}
       
  3872 
       
  3873 EXPORT_C const RArray<TAgnCalendarTime>* CAgnRptDef::SporadicDateList() const
       
  3874 /** Gets a pointer to the repeat definition's sporadic date list.
       
  3875 @return Pointer to the sporadic date list.
       
  3876 @internalComponent
       
  3877 */
       
  3878 	{
       
  3879 	return iSporadicDates;
       
  3880 	}
       
  3881 
       
  3882 const TAgnCalendarTime& CAgnRptDef::StartTime() const
       
  3883 /** Gets the start date expressed as Current System Local Time.
       
  3884 @internalComponent
       
  3885 @return The start date expressed as Current System Local Time.
       
  3886 */
       
  3887 	{
       
  3888 	return iOwningEntry.EntryTime();
       
  3889 	}
       
  3890 
       
  3891 EXPORT_C void CAgnRptDef::SetUntilTime(const TAgnCalendarTime& aUntilTime)
       
  3892 	{
       
  3893 	__ASSERT_ALWAYS(iRRule, Panic(EAgmErrNoRepeatRule));
       
  3894 	iRRule->SetUntilTime(aUntilTime);
       
  3895 	}
       
  3896 
       
  3897 EXPORT_C void CAgnRptDef::SetInterval(TUint16 aInterval)
       
  3898 	{
       
  3899 	__ASSERT_ALWAYS(iRRule, Panic(EAgmErrNoRepeatRule));
       
  3900 	iRRule->SetInterval(aInterval);
       
  3901 	}
       
  3902 
       
  3903 EXPORT_C CAgnTzRules* CAgnRptDef::AgnTzRules() const
       
  3904 	{
       
  3905 	return iTimeZone;
       
  3906 	}