|
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 } |