|
1 // Copyright (c) 2004-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 "tzdbentities.h" |
|
17 #include "ReadOnlyTzDb.h" |
|
18 #include <vtzrules.h> |
|
19 |
|
20 /** |
|
21 This const must match the last TTzRuleDay enumeration in tzdefines.h. |
|
22 @internalComponent |
|
23 */ |
|
24 const TInt KValidatedLastDayRule = ETzDayInLastWeekOfMonth; |
|
25 |
|
26 /** |
|
27 This const must match the last TTzTimeReference enumeration in tzdefines.h. |
|
28 @internalComponent |
|
29 */ |
|
30 const TInt KValidatedLastTimeReference = ETzWallTimeReference; |
|
31 |
|
32 //============================================================================= |
|
33 |
|
34 CTzDbStringsTable* CTzDbStringsTable::NewL(const TTzStringsTable& aRegionsTable) |
|
35 { |
|
36 CTzDbStringsTable* self = new(ELeave) CTzDbStringsTable(aRegionsTable); |
|
37 return self; |
|
38 } |
|
39 |
|
40 CTzDbStringsTable::CTzDbStringsTable(const TTzStringsTable& aRegionsTable) |
|
41 : iPersistedEntity(aRegionsTable) |
|
42 { |
|
43 } |
|
44 |
|
45 TPtrC8 CTzDbStringsTable::GetStringL(TUint aReferenceToString) |
|
46 { |
|
47 const TInt KStringsBaseAddress = (TInt)&iPersistedEntity; |
|
48 const TInt KLengthAddress = KStringsBaseAddress + aReferenceToString; |
|
49 const TInt KStringAddress = KLengthAddress + 1; // length occupies 1 byte |
|
50 TUint8 length = *(reinterpret_cast<TUint8*>(KLengthAddress)); |
|
51 TPtrC8 theString(reinterpret_cast<TUint8*>(KStringAddress),length); |
|
52 return theString; |
|
53 } |
|
54 |
|
55 //============================================================================= |
|
56 |
|
57 CTzDbRegionsTable* CTzDbRegionsTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionsTable& aRegionsTable) |
|
58 { |
|
59 CTzDbRegionsTable* self = new(ELeave) CTzDbRegionsTable(aReadOnlyTzDb, aRegionsTable); |
|
60 return self; |
|
61 } |
|
62 |
|
63 CTzDbRegionsTable::CTzDbRegionsTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionsTable& aRegionsTable) |
|
64 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
65 iPersistedEntity(aRegionsTable) |
|
66 { |
|
67 } |
|
68 |
|
69 // |
|
70 // Looks for a region given its name. |
|
71 // Returns the region wrapped in a CTzDbRegion object. |
|
72 // Returns NULL if region is not found |
|
73 // |
|
74 CTzDbRegion* CTzDbRegionsTable::FindRegionL(const TDesC8& aRegionName) |
|
75 { |
|
76 const TInt KRegionCount = iPersistedEntity.iNumberOfRegions; |
|
77 TTzRegion* region(NULL); |
|
78 TPtrC8 name; |
|
79 TInt regionAddress = reinterpret_cast<TInt>(&iPersistedEntity) + sizeof(iPersistedEntity.iNumberOfRegions); |
|
80 for (TInt i = 0; i < KRegionCount; i++, regionAddress += sizeof(TTzRegion)) |
|
81 { |
|
82 region = reinterpret_cast<TTzRegion*>(regionAddress); |
|
83 name.Set(iReadOnlyTzDb.GetStringL(region->iOffsetToRegionName)); |
|
84 |
|
85 // compare both strings |
|
86 if (aRegionName.Compare(name) == 0) // found our region |
|
87 { |
|
88 return CTzDbRegion::NewL(iReadOnlyTzDb,*region); |
|
89 } |
|
90 } |
|
91 |
|
92 // if it gets here, it means that the region has not been found |
|
93 return NULL; |
|
94 } |
|
95 |
|
96 //============================================================================= |
|
97 |
|
98 CTzDbRegionalZonesTable* CTzDbRegionalZonesTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionalZonesTable& aRegionalZonesTable) |
|
99 { |
|
100 CTzDbRegionalZonesTable* self = new(ELeave) CTzDbRegionalZonesTable(aReadOnlyTzDb, aRegionalZonesTable); |
|
101 return self; |
|
102 } |
|
103 |
|
104 CTzDbRegionalZonesTable::CTzDbRegionalZonesTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionalZonesTable& aRegionalZonesTable) |
|
105 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
106 iPersistedEntity(aRegionalZonesTable) |
|
107 { |
|
108 } |
|
109 |
|
110 const TTzRegionalZoneIndex& CTzDbRegionalZonesTable::GetTRegionalZoneIndex(TUint aReference) |
|
111 { |
|
112 return * reinterpret_cast<TTzRegionalZoneIndex*> (aReference + reinterpret_cast<TInt>(&iPersistedEntity)); |
|
113 } |
|
114 |
|
115 //============================================================================= |
|
116 |
|
117 CTzDbZonesTable* CTzDbZonesTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZonesTable& aZonesTable, TInt aZonesDataBaseAddress) |
|
118 { |
|
119 CTzDbZonesTable* self = new(ELeave) CTzDbZonesTable(aReadOnlyTzDb, aZonesTable, aZonesDataBaseAddress); |
|
120 return self; |
|
121 } |
|
122 |
|
123 CTzDbZonesTable::CTzDbZonesTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZonesTable& aZonesTable, TInt aZonesDataBaseAddress) |
|
124 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
125 iPersistedEntity(aZonesTable), |
|
126 iZonesDataBaseAddress(aZonesDataBaseAddress) |
|
127 { |
|
128 } |
|
129 |
|
130 CTzDbZone* CTzDbZonesTable::GetZoneL(TUint aReference) |
|
131 { |
|
132 return CTzDbZone::NewL(iReadOnlyTzDb, GetTZone(aReference)); |
|
133 } |
|
134 |
|
135 TTzZone& CTzDbZonesTable::GetTZone(TUint aReference) |
|
136 { |
|
137 return *reinterpret_cast<TTzZone*>(aReference + iZonesDataBaseAddress); |
|
138 } |
|
139 |
|
140 // |
|
141 // Performs a binary search in the zones table, looking for the zone with the |
|
142 // supplied numeric ID. |
|
143 // |
|
144 // IMPORTANT: Assumes zones are sorted by LocationId in zones table. |
|
145 // |
|
146 CTzDbZone* CTzDbZonesTable::GetZoneByIdL(TUint aNumericId) |
|
147 { |
|
148 TTzZone* tzone(NULL); |
|
149 const TInt KZoneCount = iPersistedEntity.iNumberOfZones; |
|
150 TInt start = 0; |
|
151 TInt end = KZoneCount - 1; |
|
152 TInt mid; |
|
153 TBool found = EFalse; |
|
154 while(start <= end) |
|
155 { |
|
156 mid = (end + start) / 2; |
|
157 tzone = &GetTZone(iPersistedEntity.iOffsetsToZones[mid]); |
|
158 if (aNumericId < tzone->iLocationId) |
|
159 { |
|
160 end = mid - 1; |
|
161 } |
|
162 else if (aNumericId == tzone->iLocationId) |
|
163 { |
|
164 // found our zone |
|
165 found = ETrue; |
|
166 break; |
|
167 } |
|
168 else |
|
169 { |
|
170 start = mid + 1; |
|
171 } |
|
172 } |
|
173 |
|
174 if (found) |
|
175 { |
|
176 return CTzDbZone::NewL(iReadOnlyTzDb, *tzone); |
|
177 } |
|
178 else |
|
179 { |
|
180 return NULL; |
|
181 } |
|
182 } |
|
183 |
|
184 //============================================================================= |
|
185 |
|
186 CTzDbLinksTable* CTzDbLinksTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzLinksTable& aLinksTable) |
|
187 { |
|
188 CTzDbLinksTable* self = new(ELeave) CTzDbLinksTable(aReadOnlyTzDb, aLinksTable); |
|
189 return self; |
|
190 } |
|
191 |
|
192 CTzDbLinksTable::CTzDbLinksTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzLinksTable& aLinksTable) |
|
193 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
194 iPersistedEntity(aLinksTable) |
|
195 { |
|
196 } |
|
197 |
|
198 CTzDbZone* CTzDbLinksTable::FindZoneL(const TDesC8& aLinkName) |
|
199 { |
|
200 const TInt KLinkCount = iPersistedEntity.iNumberOfLinks; |
|
201 TPtrC8 name; |
|
202 TTzLink* link(NULL); |
|
203 TInt linkAddress = reinterpret_cast<TInt>(&iPersistedEntity) + sizeof(iPersistedEntity.iNumberOfLinks); |
|
204 for (TInt i = 0; i < KLinkCount; i++, linkAddress += sizeof(TTzLink)) |
|
205 { |
|
206 link = reinterpret_cast<TTzLink*>(linkAddress); |
|
207 name.Set(iReadOnlyTzDb.GetStringL(link->iOffsetToLinkName)); |
|
208 if (!name.CompareC(aLinkName)) |
|
209 { // we found our link |
|
210 return iReadOnlyTzDb.GetZoneL(link->iOffsetToZone); |
|
211 } |
|
212 } |
|
213 |
|
214 // if it gets here, it means that the zone has not been found |
|
215 return NULL; |
|
216 } |
|
217 |
|
218 //============================================================================= |
|
219 |
|
220 CTzDbStdTimeAlignmentsTable* CTzDbStdTimeAlignmentsTable::NewL(const TTzStdTimeAlignmentsTable& aStdTimeAlignmentsTable) |
|
221 { |
|
222 CTzDbStdTimeAlignmentsTable* self = new(ELeave) CTzDbStdTimeAlignmentsTable(aStdTimeAlignmentsTable); |
|
223 return self; |
|
224 } |
|
225 |
|
226 CTzDbStdTimeAlignmentsTable::CTzDbStdTimeAlignmentsTable(const TTzStdTimeAlignmentsTable& aStdTimeAlignmentsTable) |
|
227 : iPersistedEntity(aStdTimeAlignmentsTable) |
|
228 { |
|
229 } |
|
230 |
|
231 TTzStdTimeAlignment& CTzDbStdTimeAlignmentsTable::GetTStdTimeAlignment(TUint aReference) |
|
232 { |
|
233 return *reinterpret_cast<TTzStdTimeAlignment*>(aReference + (TInt)&iPersistedEntity); |
|
234 } |
|
235 |
|
236 //============================================================================= |
|
237 |
|
238 CTzDbRuleSetsTable* CTzDbRuleSetsTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSetsTable& aRuleSetsTable) |
|
239 { |
|
240 CTzDbRuleSetsTable* self = new(ELeave) CTzDbRuleSetsTable(aReadOnlyTzDb, aRuleSetsTable); |
|
241 return self; |
|
242 } |
|
243 |
|
244 CTzDbRuleSetsTable::CTzDbRuleSetsTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSetsTable& aRuleSetsTable) |
|
245 : iReadOnlyTzDb(aReadOnlyTzDb), iPersistedEntity(aRuleSetsTable) |
|
246 { |
|
247 } |
|
248 |
|
249 CTzDbRuleSet* CTzDbRuleSetsTable::GetRuleSetL(TUint aReference) |
|
250 { |
|
251 return CTzDbRuleSet::NewL(iReadOnlyTzDb, GetTRuleSet(aReference)); |
|
252 } |
|
253 |
|
254 TTzRuleSet& CTzDbRuleSetsTable::GetTRuleSet(TUint aReference) |
|
255 { |
|
256 return * reinterpret_cast<TTzRuleSet*>(aReference + (TInt)&iPersistedEntity); |
|
257 } |
|
258 |
|
259 //============================================================================= |
|
260 |
|
261 CTzDbRuleUsesTable* CTzDbRuleUsesTable::NewL(const TTzRuleUsesTable& aRuleUsesTable) |
|
262 { |
|
263 CTzDbRuleUsesTable* self = new(ELeave) CTzDbRuleUsesTable(aRuleUsesTable); |
|
264 return self; |
|
265 } |
|
266 |
|
267 CTzDbRuleUsesTable::CTzDbRuleUsesTable(const TTzRuleUsesTable& aRuleUsesTable) |
|
268 : iPersistedEntity(aRuleUsesTable) |
|
269 { |
|
270 } |
|
271 |
|
272 TTzRuleUse& CTzDbRuleUsesTable::GetTRuleUse(TUint aReference) |
|
273 { |
|
274 return * reinterpret_cast<TTzRuleUse*> (aReference + (TInt)&iPersistedEntity); |
|
275 } |
|
276 |
|
277 //============================================================================= |
|
278 |
|
279 CTzDbRuleDefinitionsTable* CTzDbRuleDefinitionsTable::NewL(const TTzRuleDefinitionsTable& aRuleDefinitionsTable) |
|
280 { |
|
281 CTzDbRuleDefinitionsTable* self = new(ELeave) CTzDbRuleDefinitionsTable(aRuleDefinitionsTable); |
|
282 return self; |
|
283 } |
|
284 |
|
285 CTzDbRuleDefinitionsTable::CTzDbRuleDefinitionsTable(const TTzRuleDefinitionsTable& aRuleDefinitionsTable) |
|
286 : iPersistedEntity(aRuleDefinitionsTable) |
|
287 { |
|
288 } |
|
289 |
|
290 const TTzRuleDefinition& CTzDbRuleDefinitionsTable::GetRuleDefinition(TUint aReference) |
|
291 { |
|
292 return * reinterpret_cast<TTzRuleDefinition*>(aReference + (TInt)&iPersistedEntity); |
|
293 } |
|
294 |
|
295 //============================================================================= |
|
296 |
|
297 CTzDbRegion* CTzDbRegion::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegion& aRegion) |
|
298 { |
|
299 CTzDbRegion* self = new(ELeave) CTzDbRegion(aReadOnlyTzDb,aRegion); |
|
300 return self; |
|
301 } |
|
302 |
|
303 CTzDbRegion::CTzDbRegion(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegion& aRegion) |
|
304 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
305 iPersistedEntity(aRegion) |
|
306 { |
|
307 } |
|
308 |
|
309 CTzDbZone* CTzDbRegion::FindZoneL(TUint aCityNameReference) |
|
310 { |
|
311 TTzRegionalZoneIndex* zoneIndex = const_cast<TTzRegionalZoneIndex*>(&iReadOnlyTzDb.GetTRegionalZoneIndex(iPersistedEntity.iOffsetToRegionalZoneIndex)); |
|
312 const TInt KZoneCount = zoneIndex->iNumberOfZones; |
|
313 TTzZone* tzone(NULL); |
|
314 for (TInt i = 0; i < KZoneCount; i++) |
|
315 { |
|
316 tzone = const_cast<TTzZone*>(&iReadOnlyTzDb.GetTZone(zoneIndex->iOffsetsToZones[i])); |
|
317 if (tzone->iOffsetToZoneName == aCityNameReference) |
|
318 { // found our zone |
|
319 return CTzDbZone::NewL(iReadOnlyTzDb,*tzone); |
|
320 } |
|
321 } |
|
322 |
|
323 // if it gets here, it means that the zone has not been found |
|
324 return NULL; |
|
325 } |
|
326 |
|
327 CTzDbZone* CTzDbRegion::FindZoneL(const TDesC8& aCityName) |
|
328 { |
|
329 TTzZone* tzone(NULL); |
|
330 TTzRegionalZoneIndex* zoneIndex = const_cast<TTzRegionalZoneIndex*>(&iReadOnlyTzDb.GetTRegionalZoneIndex(iPersistedEntity.iOffsetToRegionalZoneIndex)); |
|
331 const TInt KZoneCount = zoneIndex->iNumberOfZones; |
|
332 TPtrC8 name; |
|
333 |
|
334 TBool found = EFalse; |
|
335 TInt start = 0; |
|
336 TInt end = KZoneCount - 1; |
|
337 TInt mid; |
|
338 |
|
339 // perform a binary search for aCityName among the zones listed in the zone index. This assumes |
|
340 // that zones are sorted alphabetically in the zone index. |
|
341 while (start <= end) |
|
342 { |
|
343 mid = (end + start) / 2; |
|
344 tzone = const_cast<TTzZone*>(&iReadOnlyTzDb.GetTZone(zoneIndex->iOffsetsToZones[mid])); |
|
345 |
|
346 // compare this zone's name with the name we've been given as a parameter |
|
347 // use strict comparison method Compare, as CompareC may cause the search to fail: |
|
348 // for example, Stanley will come BEFORE St_Helens using the standard collation method in Symbian OS, |
|
349 // but it will have been placed AFTER St_Helens by std::sort in he TZ Compiler. This would result |
|
350 // in this binary search to fail. |
|
351 name.Set(iReadOnlyTzDb.GetStringL(tzone->iOffsetToZoneName)); |
|
352 if (aCityName.Compare(name) < 0) |
|
353 { |
|
354 end = mid - 1; |
|
355 } |
|
356 else if (aCityName.Compare(name) == 0) |
|
357 { // found our zone |
|
358 found = ETrue; |
|
359 break; |
|
360 } |
|
361 else if (aCityName.Compare(name) > 0) |
|
362 { |
|
363 start = mid + 1; |
|
364 } |
|
365 } |
|
366 |
|
367 if (found) |
|
368 { |
|
369 return CTzDbZone::NewL(iReadOnlyTzDb,*tzone); |
|
370 } |
|
371 else |
|
372 { |
|
373 return NULL; |
|
374 } |
|
375 } |
|
376 |
|
377 //============================================================================= |
|
378 |
|
379 CTzDbZone* CTzDbZone::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZone& aZone) |
|
380 { |
|
381 CTzDbZone* self = new(ELeave) CTzDbZone(aReadOnlyTzDb,aZone); |
|
382 return self; |
|
383 } |
|
384 |
|
385 CTzDbZone::CTzDbZone(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZone& aZone) |
|
386 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
387 iPersistedEntity(aZone) |
|
388 { |
|
389 } |
|
390 |
|
391 void CTzDbZone::GetRulesL(CTzRules& aRules) |
|
392 { |
|
393 // start and end years of interest |
|
394 TInt firstYearOfInterest = aRules.StartYear(); |
|
395 TInt lastYearOfInterest = aRules.EndYear(); |
|
396 |
|
397 // record last instant of end year, in order to see if we need to get another time alignment |
|
398 TDateTime endDateTimeOfInterest(lastYearOfInterest,EDecember,30,23,59,59,0); |
|
399 TTime endTimeOfInterest(endDateTimeOfInterest); |
|
400 |
|
401 // initialise start time to beginning of startYear (UTC) |
|
402 TDateTime startDateTime(firstYearOfInterest,EJanuary,0,0,0,0,0); |
|
403 TTime startTime(startDateTime); |
|
404 TTime staEndTime; |
|
405 TDateTime staEndDateTime; |
|
406 TTzTimeReference staTimeReference(ETzUtcTimeReference); |
|
407 |
|
408 // the following variables are used to iterate through the list of standard time alignments for this location |
|
409 TInt taCount = iPersistedEntity.iNumberOfStdTimeAlignments; |
|
410 TInt tmpOffset; |
|
411 TTzStdTimeAlignment* ta(NULL); |
|
412 TTzStdTimeAlignment* prevTa(NULL); |
|
413 CTzDbStdTimeAlignment* sta = NULL; |
|
414 |
|
415 // the standard time offset at the beginning of the period of interest has to be set in aTzRules |
|
416 TBool initialOffsetHasBeenSet = EFalse; |
|
417 |
|
418 // Iterate through std time alignments until we find the one that contains our date of interest. |
|
419 // Get the rules for this time alignment, up to the end of the time alignment or the end of our |
|
420 // period of interest (whichever comes first). |
|
421 // If the period of interest is covered by only one time alignment, finish and return. |
|
422 // If the period of interest is covered by more than one time alignment, repeat procedure with |
|
423 // next time alignment(s) until we reach the end of the period of interest |
|
424 for (TInt i = 0; (i < taCount) && (startTime < endTimeOfInterest ); i++) |
|
425 { |
|
426 // get a standard time alignment |
|
427 |
|
428 prevTa = ta; // this will be needed to eventually wrap the time alignment in a CTzDbStdTimeAlignment object |
|
429 tmpOffset = iPersistedEntity.iOffsetsToTimeAlignments[i]; |
|
430 ta = const_cast<TTzStdTimeAlignment*>(&iReadOnlyTzDb.GetTStdTimeAlignment(tmpOffset)); |
|
431 |
|
432 // check if our time of interest is within this time alignment |
|
433 if (IsTimeInStdTimeAlignment(*ta, startDateTime.Year(), |
|
434 startDateTime.Month(), |
|
435 startDateTime.Day(), |
|
436 startDateTime.Hour(), |
|
437 startDateTime.Minute(), |
|
438 staTimeReference) ) |
|
439 { |
|
440 // wrap the time alignment in a CTzDbStdTimeAlignment object |
|
441 sta = CTzDbStdTimeAlignment::NewL(iReadOnlyTzDb,*ta,prevTa); |
|
442 if (sta) |
|
443 { |
|
444 CleanupStack::PushL(sta); // push #1 - sta |
|
445 |
|
446 if (initialOffsetHasBeenSet == EFalse) |
|
447 { |
|
448 aRules.SetInitialStdTimeOffset(ta->iUtcOffset); |
|
449 initialOffsetHasBeenSet = ETrue; |
|
450 } |
|
451 |
|
452 // staStartDateTime, staEndTime are passed by reference and their values |
|
453 // are updated in GetRulesL |
|
454 sta->GetRulesL(aRules,startDateTime,staEndDateTime); |
|
455 |
|
456 // The time reference to calculate the start of the next time alignment is the time reference |
|
457 // in which the end time of this time alignment is expressed |
|
458 staTimeReference = static_cast<TTzTimeReference>(sta->UntilTimeReference()); |
|
459 CleanupStack::PopAndDestroy(sta); // pop #1 - sta |
|
460 |
|
461 staEndTime = staEndDateTime; |
|
462 if (staEndTime == Time::MaxTTime()) |
|
463 { |
|
464 startTime = staEndTime; // this will cause loop to finish |
|
465 } |
|
466 else |
|
467 { |
|
468 // move just after end of time alignment |
|
469 startTime = staEndTime + static_cast<TTimeIntervalSeconds>(1); |
|
470 startDateTime = startTime.DateTime(); |
|
471 } |
|
472 } |
|
473 } // if IsTimeInStdTimeAlignment(...) |
|
474 } // for |
|
475 |
|
476 } |
|
477 |
|
478 TBool CTzDbZone::IsTimeInStdTimeAlignment(const TTzStdTimeAlignment& aStdTa, TInt aYear, TInt aMonth, TInt aDay, TInt aHour, TInt aMinute, TTzTimeReference aTimeRef) |
|
479 { |
|
480 TInt found = EFalse; |
|
481 |
|
482 if (aYear > (TInt)KMaxTUint16) |
|
483 { |
|
484 aYear = KMaxTUint16; // KMaxTUint16 (0xFFFF) is the value given to year when the end of a time alignment is unknown |
|
485 } |
|
486 |
|
487 if (aStdTa.iUntilYear > aYear) |
|
488 { |
|
489 found = ETrue; |
|
490 } |
|
491 else if (aStdTa.iUntilYear == aYear) |
|
492 { |
|
493 if ( (aStdTa.iUntilMonth > aMonth) || (aStdTa.iUntilMonth == KMaxTUint8) ) |
|
494 { |
|
495 found = ETrue; |
|
496 } |
|
497 else if (aStdTa.iUntilMonth == aMonth) |
|
498 { |
|
499 // evaluate the day and time the time alignment ends |
|
500 // and see if the received time falls in or out of the t.a. |
|
501 TTime ourTime; |
|
502 |
|
503 if (aYear >= (TInt)KMaxTUint16) |
|
504 { |
|
505 ourTime = Time::MaxTTime(); |
|
506 } |
|
507 else |
|
508 { |
|
509 TDateTime ourDateTime(aYear, |
|
510 (TMonth)aMonth, |
|
511 aDay, |
|
512 aHour, |
|
513 aMinute, |
|
514 0, |
|
515 0); |
|
516 |
|
517 ourTime = ourDateTime; |
|
518 |
|
519 // convert ourTime to UTC |
|
520 if (aTimeRef == ETzStdTimeReference) |
|
521 { |
|
522 ourTime -= static_cast<TTimeIntervalMinutes>(aStdTa.iUtcOffset); |
|
523 } |
|
524 } |
|
525 |
|
526 TTime endTime; |
|
527 if (aStdTa.iUntilYear == KMaxTUint16) |
|
528 { |
|
529 endTime = Time::MaxTTime(); |
|
530 } |
|
531 else |
|
532 { |
|
533 TDateTime endDateTime(aStdTa.iUntilYear, |
|
534 (TMonth)aStdTa.iUntilMonth, |
|
535 aStdTa.iUntilDayOfMonth, |
|
536 (aStdTa.iUntilTimeInMinutes / 60), |
|
537 (aStdTa.iUntilTimeInMinutes % 60), |
|
538 0, |
|
539 0); |
|
540 |
|
541 endTime = endDateTime; |
|
542 |
|
543 // convert endTime to UTC |
|
544 if (aTimeRef == ETzStdTimeReference) |
|
545 { |
|
546 endTime -= static_cast<TTimeIntervalMinutes>(aStdTa.iUtcOffset); |
|
547 } |
|
548 } |
|
549 |
|
550 // and finally compare both times |
|
551 if (endTime >= ourTime) |
|
552 { |
|
553 found = ETrue; |
|
554 } |
|
555 } |
|
556 } // else if (aStdTa->iUntilYear == aYear) |
|
557 |
|
558 return found; |
|
559 } |
|
560 // |
|
561 // Traverses the collection of Std Time Alignments for the current zone, looking for the one that |
|
562 // matches the given time. |
|
563 // Returns a CTzDbStdTimeAlignment object. |
|
564 // |
|
565 CTzDbStdTimeAlignment* CTzDbZone::FindStdTimeAlignmentL(TInt aYear, TInt aMonth, TInt aDay, TInt aHour, TInt aMinute, const TTzTimeReference aTimeRef) |
|
566 { |
|
567 TTzStdTimeAlignment* ta(NULL); |
|
568 TTzStdTimeAlignment* prevTa(NULL); |
|
569 TInt taCount = iPersistedEntity.iNumberOfStdTimeAlignments; |
|
570 TBool found = EFalse; |
|
571 TInt tmpOffset = 0; |
|
572 for (TInt i = 0; (i < taCount) && (!found); i++) |
|
573 { |
|
574 prevTa = ta; |
|
575 tmpOffset = iPersistedEntity.iOffsetsToTimeAlignments[i]; |
|
576 ta = const_cast<TTzStdTimeAlignment*>(&iReadOnlyTzDb.GetTStdTimeAlignment(tmpOffset)); |
|
577 |
|
578 found = IsTimeInStdTimeAlignment(*ta,aYear,aMonth,aDay,aHour,aMinute,aTimeRef); |
|
579 } |
|
580 |
|
581 if (found) |
|
582 { |
|
583 return CTzDbStdTimeAlignment::NewL(iReadOnlyTzDb, *ta, prevTa); |
|
584 } |
|
585 else |
|
586 { |
|
587 return NULL; |
|
588 } |
|
589 } |
|
590 |
|
591 HBufC8* CTzDbZone::GetFullZoneNameLC() |
|
592 { |
|
593 HBufC8* fullName = HBufC8::NewL(KMaxTimeZoneIdSize); |
|
594 CleanupStack::PushL(fullName); |
|
595 TPtr8 fullNamePtr(fullName->Des() ); |
|
596 fullNamePtr.Append(iReadOnlyTzDb.GetStringL(iPersistedEntity.iOffsetToRegionName)); |
|
597 if (fullNamePtr.Length() > 0) |
|
598 { |
|
599 // if the region name is empty (e.g. zone "CET"), don't add the slash |
|
600 fullNamePtr.Append('/'); |
|
601 } |
|
602 fullNamePtr.Append(iReadOnlyTzDb.GetStringL(iPersistedEntity.iOffsetToZoneName)); |
|
603 |
|
604 return fullName; |
|
605 } |
|
606 |
|
607 //======================================================================== |
|
608 |
|
609 CTzDbStdTimeAlignment* CTzDbStdTimeAlignment::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzStdTimeAlignment& aTimeAlignment, TTzStdTimeAlignment* aPrevTimeAlignment) |
|
610 { |
|
611 CTzDbStdTimeAlignment* self = new(ELeave) CTzDbStdTimeAlignment(aReadOnlyTzDb,aTimeAlignment,aPrevTimeAlignment); |
|
612 return self; |
|
613 } |
|
614 |
|
615 CTzDbStdTimeAlignment::CTzDbStdTimeAlignment(CReadOnlyTzDb& aReadOnlyTzDb, |
|
616 const TTzStdTimeAlignment& aTimeAlignment, TTzStdTimeAlignment* aPrevTimeAlignment) |
|
617 : iReadOnlyTzDb(aReadOnlyTzDb) |
|
618 { |
|
619 iPersistedEntity = aTimeAlignment; |
|
620 iPrevTimeAlignment = aPrevTimeAlignment; |
|
621 } |
|
622 |
|
623 CTzDbStdTimeAlignment::~CTzDbStdTimeAlignment() |
|
624 { |
|
625 } |
|
626 |
|
627 void CTzDbStdTimeAlignment::GetRulesL(CTzRules& aRules, const TDateTime& aStartDateTime, TDateTime& aEndDateTime) |
|
628 { |
|
629 // get the ruleSet for this time alignment |
|
630 CTzDbRuleSet* ruleSet = iReadOnlyTzDb.GetRuleSetL(iPersistedEntity.iOffsetToRuleSet); |
|
631 if (ruleSet) |
|
632 { |
|
633 CleanupStack::PushL(ruleSet); // PUSH #1 - RULESET |
|
634 |
|
635 // get end time of time alignment |
|
636 TTime endTime; |
|
637 CalculateEndTime(endTime); |
|
638 if (endTime == Time::MaxTTime()) |
|
639 { |
|
640 aEndDateTime.SetYear(KMaxTUint16); |
|
641 } |
|
642 else |
|
643 { |
|
644 aEndDateTime = endTime.DateTime(); |
|
645 } |
|
646 |
|
647 TInt firstYearOfInterest = (aRules.StartYear() >= aStartDateTime.Year()) ? aRules.StartYear() : aStartDateTime.Year(); |
|
648 TInt lastYearOfInterest = (aRules.EndYear() <= aEndDateTime.Year()) ? aRules.EndYear() : aEndDateTime.Year(); |
|
649 CTzRules* newRules = CTzRules::NewL(firstYearOfInterest, lastYearOfInterest); |
|
650 CleanupStack::PushL(newRules); // PUSH #2 - NEWRULES |
|
651 |
|
652 ruleSet->GetRulesL(*newRules,iPersistedEntity.iUtcOffset,aStartDateTime,aEndDateTime); |
|
653 |
|
654 // the new rules obtained for the current std time alignment must be merged into |
|
655 // the global rule collection |
|
656 AddRulesToCollectionL(aRules,*newRules); |
|
657 |
|
658 CleanupStack::PopAndDestroy(2, ruleSet); // POP #2,#1 - NEWRULES, RULESET |
|
659 } |
|
660 } |
|
661 |
|
662 void CTzDbStdTimeAlignment::AddRulesToCollectionL(CTzRules& aRuleCollection, CTzRules& aNewRules) |
|
663 { |
|
664 TTzRule* tRule(NULL); |
|
665 TVTzActualisedRule tActRule; |
|
666 TInt count = aNewRules.Count(); |
|
667 for (TInt i = 0; i < count; i++) |
|
668 { |
|
669 TBool ruleAdded = EFalse; |
|
670 tRule = &(aNewRules[i]); |
|
671 TInt basicRuleFromYear = tRule->iFrom.iTime.DateTime().Year(); |
|
672 TInt basicRuleToYear = tRule->iTo.iTime.DateTime().Year(); |
|
673 |
|
674 if ( (iPrevTimeAlignment != NULL) |
|
675 && (basicRuleFromYear <= iPrevTimeAlignment->iUntilYear) |
|
676 && (basicRuleToYear >= iPrevTimeAlignment->iUntilYear) ) |
|
677 { // the rule is in effect during the first year of the time alignment |
|
678 // actualise rule for this year and remove it if it falls outside the time alignment |
|
679 tActRule = tRule->Actualise(iPrevTimeAlignment->iUntilYear); |
|
680 |
|
681 // work out start time of time alignment (i.e. end time of the prev. alignment) |
|
682 |
|
683 TDateTime staStartDateTime( iPrevTimeAlignment->iUntilYear, |
|
684 (TMonth)iPrevTimeAlignment->iUntilMonth, |
|
685 iPrevTimeAlignment->iUntilDayOfMonth, |
|
686 iPrevTimeAlignment->iUntilTimeInMinutes/60, // hour |
|
687 iPrevTimeAlignment->iUntilTimeInMinutes%60, // minute |
|
688 0,0); // second, ms |
|
689 |
|
690 // make sure times are expressed in the same reference (UTC or Local) |
|
691 if (tActRule.iTimeReference != iPrevTimeAlignment->iUntilTimeReference) |
|
692 { |
|
693 if (iPrevTimeAlignment->iUntilTimeReference == ETzWallTimeReference) |
|
694 { // convert sta start time to UTC |
|
695 TTime staTime(staStartDateTime); |
|
696 staTime -= (TTimeIntervalMinutes)(iPrevTimeAlignment->iUtcOffset); |
|
697 staStartDateTime = staTime.DateTime(); |
|
698 } |
|
699 else if (iPrevTimeAlignment->iUntilTimeReference == ETzUtcTimeReference) |
|
700 { // convert time of change to UTC |
|
701 tActRule.iTimeOfChange -= (TTimeIntervalMinutes)tRule->iOldLocalTimeOffset; |
|
702 } |
|
703 } |
|
704 |
|
705 // add rule to collection only if its time of change falls within the time alignment |
|
706 if (tActRule.iTimeOfChange >= staStartDateTime) |
|
707 { |
|
708 aRuleCollection.AddRuleL(*tRule); |
|
709 ruleAdded = ETrue; |
|
710 } |
|
711 else |
|
712 { |
|
713 TDateTime tActRuleDt = tActRule.iTimeOfChange.DateTime(); |
|
714 /* |
|
715 Fix for INC117764: |
|
716 Update the rule's month and daytime information only if the rule starts and ends in the same year |
|
717 otherwise just add them to the collection. |
|
718 For example: |
|
719 Iqaluit rules: |
|
720 -6:00 Canada C%sT 2000 Oct 29 2:00 |
|
721 -5:00 Canada E%sT |
|
722 |
|
723 Rule Canada 1974 2006 - Oct lastSun 2:00 0 S |
|
724 Rule Canada 1987 2006 - Apr Sun>=1 2:00 1:00 D |
|
725 Rule Canada 2007 max - Mar Sun>=8 2:00 1:00 D |
|
726 Rule Canada 2007 max - Nov Sun>=1 2:00 0 S |
|
727 Before this fix, In such a case for all the rules between 2000 and 2006 would be overwritten with start month as 10 whereas they |
|
728 should be alternating between October and April till 2006. |
|
729 */ |
|
730 if ((tActRuleDt.Year() == staStartDateTime.Year()) && (basicRuleFromYear == basicRuleToYear) ) |
|
731 { |
|
732 tRule->iMonth = staStartDateTime.Month(); |
|
733 tRule->iDayOfMonth = staStartDateTime.Day(); |
|
734 tRule->iDayRule = ETzFixedDate; |
|
735 aRuleCollection.AddRuleL(*tRule); |
|
736 ruleAdded = ETrue; |
|
737 } |
|
738 else if (tActRuleDt.Year() == staStartDateTime.Year()) |
|
739 { |
|
740 aRuleCollection.AddRuleL(*tRule); |
|
741 ruleAdded = ETrue; |
|
742 } |
|
743 } |
|
744 } |
|
745 else if ( |
|
746 (tRule->iFrom.iTime.DateTime().Year() <= iPersistedEntity.iUntilYear) |
|
747 &&(tRule->iTo.iTime.DateTime().Year() >= iPersistedEntity.iUntilYear) |
|
748 ) |
|
749 { |
|
750 // the rule is in effect during the last year of the time alignment |
|
751 tActRule = tRule->Actualise(iPersistedEntity.iUntilYear); |
|
752 |
|
753 TDateTime staEndDateTime(iPersistedEntity.iUntilYear, (TMonth)iPersistedEntity.iUntilMonth, |
|
754 iPersistedEntity.iUntilDayOfMonth, |
|
755 iPersistedEntity.iUntilTimeInMinutes / 60, // hour |
|
756 iPersistedEntity.iUntilTimeInMinutes % 60, // minute |
|
757 0,0); // second, ms |
|
758 |
|
759 if (tActRule.iTimeReference != iPersistedEntity.iUntilTimeReference) |
|
760 { |
|
761 if (iPersistedEntity.iUntilTimeReference == ETzWallTimeReference) |
|
762 { |
|
763 TTime staTime(staEndDateTime); |
|
764 staTime -= (TTimeIntervalMinutes)iPersistedEntity.iUtcOffset; |
|
765 staEndDateTime = staTime.DateTime(); |
|
766 } |
|
767 else if (iPersistedEntity.iUntilTimeReference == ETzUtcTimeReference) |
|
768 { |
|
769 tActRule.iTimeOfChange -= (TTimeIntervalMinutes)tRule->iOldLocalTimeOffset; |
|
770 } |
|
771 } |
|
772 |
|
773 // add rule to collection only if its time of change falls withing the time alignment |
|
774 if (tActRule.iTimeOfChange < staEndDateTime) |
|
775 { |
|
776 aRuleCollection.AddRuleL(*tRule); |
|
777 ruleAdded = ETrue; |
|
778 } |
|
779 } |
|
780 else |
|
781 { |
|
782 // no doubt that the rule falls within the time alignment |
|
783 aRuleCollection.AddRuleL(*tRule); |
|
784 ruleAdded = ETrue; |
|
785 } |
|
786 /* |
|
787 Fix for INC117764: |
|
788 Updating the default rule for a year if any new rule overlaps with the default rule.(Default rules start and end at same time) |
|
789 The offsets are updated if default rule and newly added rule start during same time and newly added rule month occurs before |
|
790 the default rule month. |
|
791 */ |
|
792 if( ruleAdded ) |
|
793 { |
|
794 if(basicRuleFromYear != basicRuleToYear) |
|
795 { |
|
796 TInt ruleCount = aRuleCollection.Count() - 2; |
|
797 for(TInt loop = ruleCount;loop >= 0; --loop) |
|
798 { |
|
799 TTzRule prevAddedRule = aRuleCollection[loop]; |
|
800 //check that we do not update a winter rule using a summer rule and vice versa |
|
801 //Summer rules start before July and winter rules after |
|
802 if(tRule->iMonth < EJuly && prevAddedRule.iMonth > EJuly) |
|
803 { |
|
804 continue; |
|
805 } |
|
806 if(tRule->iMonth > EJuly && prevAddedRule.iMonth < EJuly) |
|
807 { |
|
808 continue; |
|
809 } |
|
810 if(basicRuleFromYear > prevAddedRule.iFrom.iTime.DateTime().Year()) |
|
811 { |
|
812 //no need to check beyond the newly added rules start year. |
|
813 break; |
|
814 } |
|
815 if((tRule->iFrom == prevAddedRule.iFrom) && |
|
816 (prevAddedRule.iFrom == prevAddedRule.iTo) && |
|
817 (tRule->iMonth < prevAddedRule.iMonth)) |
|
818 { |
|
819 prevAddedRule.iOldLocalTimeOffset = tRule->iOldLocalTimeOffset; |
|
820 prevAddedRule.iNewLocalTimeOffset = tRule->iNewLocalTimeOffset; |
|
821 aRuleCollection.RemoveRule(loop); |
|
822 aRuleCollection.AddRuleL(prevAddedRule); |
|
823 } |
|
824 } |
|
825 } |
|
826 } |
|
827 } // for |
|
828 } |
|
829 |
|
830 TInt CTzDbStdTimeAlignment::UtcOffset() |
|
831 { |
|
832 return iPersistedEntity.iUtcOffset; |
|
833 } |
|
834 |
|
835 TUint CTzDbStdTimeAlignment::RuleSetReference() |
|
836 { |
|
837 return iPersistedEntity.iOffsetToRuleSet; |
|
838 } |
|
839 |
|
840 TInt CTzDbStdTimeAlignment::UntilYear() |
|
841 { |
|
842 return iPersistedEntity.iUntilYear; |
|
843 } |
|
844 |
|
845 TInt CTzDbStdTimeAlignment::UntilMonth() |
|
846 { |
|
847 return iPersistedEntity.iUntilMonth; |
|
848 } |
|
849 |
|
850 TInt CTzDbStdTimeAlignment::UntilDay() |
|
851 { |
|
852 return iPersistedEntity.iUntilDayOfMonth; |
|
853 } |
|
854 |
|
855 TInt CTzDbStdTimeAlignment::UntilTimeInMinutes() |
|
856 { |
|
857 return iPersistedEntity.iUntilTimeInMinutes; |
|
858 } |
|
859 |
|
860 TInt CTzDbStdTimeAlignment::UntilTimeReference() |
|
861 { |
|
862 return iPersistedEntity.iUntilTimeReference; |
|
863 } |
|
864 |
|
865 // |
|
866 // Calculate End Time of TimeAlignment (UTC) |
|
867 // |
|
868 void CTzDbStdTimeAlignment::CalculateEndTime(TTime& aEndTime) |
|
869 { |
|
870 TInt endYear; |
|
871 TInt endMonth; |
|
872 TInt endDay; |
|
873 TInt endHour; |
|
874 TInt endMinute; |
|
875 TInt endSecond = 0; |
|
876 TInt endMicrosecond = 0; |
|
877 |
|
878 if (iPersistedEntity.iUntilYear == KMaxTUint16) |
|
879 { |
|
880 aEndTime = Time::MaxTTime(); |
|
881 } |
|
882 else |
|
883 { |
|
884 |
|
885 endYear = iPersistedEntity.iUntilYear; |
|
886 endMonth = iPersistedEntity.iUntilMonth; if (endMonth > EDecember) endMonth = EJanuary; |
|
887 endDay = iPersistedEntity.iUntilDayOfMonth; if (endDay > 31) endDay = 0; |
|
888 if (iPersistedEntity.iUntilTimeInMinutes == KMaxTUint16) |
|
889 { |
|
890 endHour = endMinute = 0; |
|
891 } |
|
892 else |
|
893 { |
|
894 endHour = iPersistedEntity.iUntilTimeInMinutes / 60; |
|
895 endMinute = iPersistedEntity.iUntilTimeInMinutes % 60; |
|
896 } |
|
897 |
|
898 TDateTime endDateTime(endYear,(TMonth)endMonth,endDay,endHour,endMinute,endSecond,endMicrosecond); |
|
899 aEndTime = endDateTime; |
|
900 |
|
901 // convert time to UTC |
|
902 TTzTimeReference taTimeReference(static_cast<TTzTimeReference>(iPersistedEntity.iUntilTimeReference) ); |
|
903 if (taTimeReference == ETzStdTimeReference) |
|
904 { |
|
905 aEndTime -= static_cast<TTimeIntervalMinutes>(iPersistedEntity.iUtcOffset); |
|
906 } |
|
907 |
|
908 // aEndTime is, at this point, the beginning of the the next Std Time Alignment |
|
909 aEndTime -= static_cast<TTimeIntervalSeconds>(1); |
|
910 } |
|
911 } |
|
912 |
|
913 // |
|
914 // Calculate Start Time of TimeAlignment (UTC) |
|
915 // |
|
916 void CTzDbStdTimeAlignment::CalculateStartTime(TTime& aStartTime) |
|
917 { |
|
918 TInt startYear; |
|
919 TInt startMonth; |
|
920 TInt startDay; |
|
921 TInt startHour; |
|
922 TInt startMinute; |
|
923 TInt startSecond = 0; |
|
924 TInt startMicrosecond = 0; |
|
925 |
|
926 if (iPrevTimeAlignment == NULL) |
|
927 { |
|
928 aStartTime = 0; |
|
929 } |
|
930 else |
|
931 { |
|
932 startYear = iPrevTimeAlignment->iUntilYear; |
|
933 startMonth = iPrevTimeAlignment->iUntilMonth; if (startMonth == (TInt)KMaxTUint8) startMonth = EJanuary; |
|
934 startDay = iPrevTimeAlignment->iUntilDayOfMonth; if (startDay == (TInt)KMaxTUint8) startDay = 0; |
|
935 if (iPrevTimeAlignment->iUntilTimeInMinutes == KMaxTUint16) |
|
936 { |
|
937 startHour = startMinute = 0; |
|
938 } |
|
939 else |
|
940 { |
|
941 startHour = iPrevTimeAlignment->iUntilTimeInMinutes / 60; |
|
942 startMinute = iPrevTimeAlignment->iUntilTimeInMinutes % 60; |
|
943 } |
|
944 |
|
945 TDateTime startDateTime(startYear,(TMonth)startMonth,startDay,startHour,startMinute,startSecond,startMicrosecond); |
|
946 aStartTime = startDateTime; |
|
947 // convert time to UTC |
|
948 TTzTimeReference taTimeReference(static_cast<TTzTimeReference>(iPersistedEntity.iUntilTimeReference) ); |
|
949 if (taTimeReference == ETzStdTimeReference) |
|
950 { |
|
951 aStartTime -= static_cast<TTimeIntervalMinutes>(iPersistedEntity.iUtcOffset); |
|
952 } |
|
953 } |
|
954 } |
|
955 |
|
956 //======================================================================== |
|
957 |
|
958 CTzDbRuleSet* CTzDbRuleSet::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSet& aRuleSet) |
|
959 { |
|
960 CTzDbRuleSet* self = new(ELeave) CTzDbRuleSet(aReadOnlyTzDb,aRuleSet); |
|
961 return self; |
|
962 } |
|
963 |
|
964 |
|
965 CTzDbRuleSet::CTzDbRuleSet(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSet& aRuleSet) |
|
966 : iReadOnlyTzDb(aReadOnlyTzDb), |
|
967 iPersistedEntity(aRuleSet) |
|
968 { |
|
969 } |
|
970 |
|
971 // |
|
972 // Gets the encoded rules for the current standard time alignment, between aStartDateTime and aEndDateTime |
|
973 // |
|
974 void CTzDbRuleSet::GetRulesL(CTzRules& aTzRules, TInt aUtcOffset, const TDateTime& aStartDateTime, const TDateTime& aEndDateTime) const |
|
975 { |
|
976 TInt startYear = aStartDateTime.Year(); |
|
977 // the last year we are interested in is the earliest of the following: |
|
978 // 1) the last year of the CTzRules |
|
979 // 2) the year of aEndDateTime (the end of the invoking std time alignment) |
|
980 |
|
981 TInt endYear = (aEndDateTime.Year() < aTzRules.EndYear()) |
|
982 ? aEndDateTime.Year() : aTzRules.EndYear(); |
|
983 const TDateTime rulesEndDateTime(aTzRules.EndYear(), EDecember, 30, 0,0,0,0); |
|
984 const TDateTime& endDateTime = (aEndDateTime.Year() <= aTzRules.EndYear()) |
|
985 ? aEndDateTime : rulesEndDateTime; |
|
986 |
|
987 RArray<TTzRuleDefinition*> ruleDefs; |
|
988 CleanupClosePushL(ruleDefs); // PUSH #1 |
|
989 RArray<TTzRuleUse*> ruleUses; |
|
990 CleanupClosePushL(ruleUses); // PUSH #2 |
|
991 |
|
992 FetchRuleDefinitionsL(ruleDefs,ruleUses,startYear,endYear); |
|
993 |
|
994 // fetch rules for previous year (these will be needed to work out the "Old Offset" field of |
|
995 // the first rule in aStartYear |
|
996 TInt initialLocalTimeOffset = GetLocalTimeOffsetAtEndOfYearL(startYear-1,aUtcOffset); |
|
997 |
|
998 // convert rule definitions (together with rule uses) to TTzRules and add them to aTzRules |
|
999 |
|
1000 CompleteRulesAndAddToCollectionL(aTzRules,ruleDefs,ruleUses,aUtcOffset,initialLocalTimeOffset,aStartDateTime,endDateTime); |
|
1001 |
|
1002 CleanupStack::PopAndDestroy(2,&ruleDefs); // POP #2,#1 - ruleUses, ruleDefs |
|
1003 } |
|
1004 |
|
1005 TInt CTzDbRuleSet::GetLocalTimeOffsetAtEndOfYearL(TInt aYear, TInt aUtcOffset) const |
|
1006 { |
|
1007 RArray<TTzRuleDefinition*> ruleDefs; |
|
1008 CleanupClosePushL(ruleDefs); |
|
1009 RArray<TTzRuleUse*> ruleUses; |
|
1010 CleanupClosePushL(ruleUses); |
|
1011 |
|
1012 TDateTime startDateTime(aYear,EJanuary,0,0,0,0,0); |
|
1013 TDateTime endDateTime(aYear,EDecember,30,23,59,59,0); |
|
1014 |
|
1015 FetchRuleDefinitionsL(ruleDefs,ruleUses,aYear,aYear); |
|
1016 |
|
1017 CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(aYear,aYear); |
|
1018 CleanupStack::PushL(actRules); |
|
1019 TVTzActualisedRule tDefaultRule(startDateTime,aUtcOffset,ETzUtcTimeReference); |
|
1020 ActualiseRuleDefinitionsL(*actRules,ruleDefs,ruleUses,aUtcOffset,startDateTime,endDateTime,tDefaultRule); |
|
1021 |
|
1022 TInt count = actRules->Count(); |
|
1023 TInt finalOffset = (*actRules)[count-1].iNewOffset; |
|
1024 |
|
1025 CleanupStack::PopAndDestroy(3,&ruleDefs); |
|
1026 return finalOffset; |
|
1027 } |
|
1028 |
|
1029 |
|
1030 void CTzDbRuleSet::CompleteRulesAndAddToCollectionL( |
|
1031 CTzRules& aTzRules, |
|
1032 const RArray<TTzRuleDefinition*>& aRuleDefs, |
|
1033 const RArray<TTzRuleUse*>& aRuleUses, |
|
1034 TInt aUtcOffset, TInt aInitialLocalTimeOffset, |
|
1035 TDateTime aStart, TDateTime aEnd) const |
|
1036 { |
|
1037 TInt count = aRuleDefs.Count(); |
|
1038 if (count != aRuleUses.Count()) |
|
1039 { |
|
1040 User::Leave(KErrCorrupt); |
|
1041 } |
|
1042 |
|
1043 TTimeWithReference startOfAlignment(aStart,ETzUtcTimeReference); |
|
1044 TTimeWithReference endOfAlignment(aEnd,ETzUtcTimeReference); |
|
1045 |
|
1046 //Keep track of changes to UTC offset |
|
1047 // even if there are no DST rules. |
|
1048 TTzRule trule( |
|
1049 startOfAlignment, startOfAlignment, |
|
1050 (TUint16)aInitialLocalTimeOffset, (TUint16)aInitialLocalTimeOffset, EJanuary, ETzFixedDate, |
|
1051 0, 0, |
|
1052 ETzUtcTimeReference, |
|
1053 0); |
|
1054 aTzRules.AddRuleL(trule); |
|
1055 //Calculate the new and old offsets for each rule. |
|
1056 TInt prevOffset = 0; |
|
1057 TInt maxOffset = 0; |
|
1058 for (TInt i = 0; i < count; i++) |
|
1059 { |
|
1060 TInt oldOffset = aInitialLocalTimeOffset; |
|
1061 TInt dstOffset = aRuleDefs[i]->iStdTimeOffset; |
|
1062 TInt newOffset = aUtcOffset + dstOffset; |
|
1063 //newoffset and oldoffset should always have a difference of dstoffset. |
|
1064 if (newOffset <= oldOffset ) |
|
1065 { |
|
1066 //there are cases when dstoffset in the set of rules is same for few continuous rules |
|
1067 //in such cases, newoffset and oldoffset would have a difference of maxoffset. |
|
1068 if(prevOffset == dstOffset) |
|
1069 { |
|
1070 oldOffset = aUtcOffset + maxOffset; |
|
1071 } |
|
1072 else |
|
1073 { |
|
1074 oldOffset = aUtcOffset + prevOffset; |
|
1075 } |
|
1076 } |
|
1077 else |
|
1078 //newoffset is more than oldoffset so maintain the difference with dstoffset. |
|
1079 { |
|
1080 oldOffset = newOffset - dstOffset; |
|
1081 } |
|
1082 prevOffset = dstOffset; |
|
1083 //store maximum offset, to handle cases in which dstoffset in the set of rules |
|
1084 //is same for few continuous rules |
|
1085 if(dstOffset > maxOffset) |
|
1086 { |
|
1087 maxOffset = dstOffset; |
|
1088 } |
|
1089 |
|
1090 TUint16 timeOfChange = aRuleDefs[i]->iTimeOfChange; |
|
1091 TTzTimeReference timeReference = |
|
1092 static_cast<TTzTimeReference>(aRuleDefs[i]->iTimeReference); |
|
1093 |
|
1094 // |
|
1095 |
|
1096 // Find the intersection of the date ranges: |
|
1097 // use latest start year, earliest end year |
|
1098 TDateTime start = aStart; |
|
1099 TDateTime end = aEnd; |
|
1100 if(aRuleUses[i]->iFromYear > start.Year()) |
|
1101 { |
|
1102 start = TDateTime(aRuleUses[i]->iFromYear,EJanuary,0,0,0,0,0); |
|
1103 } |
|
1104 |
|
1105 if(aEnd.Year() > aRuleUses[i]->iUntilYear) |
|
1106 { |
|
1107 end = TDateTime(aRuleUses[i]->iUntilYear,EDecember,30,23,59,59,0); |
|
1108 } |
|
1109 |
|
1110 TTimeWithReference startOfRule(start,ETzUtcTimeReference); |
|
1111 TTimeWithReference endOfRule(end,ETzUtcTimeReference); |
|
1112 if(endOfRule.iTime >= startOfRule.iTime) |
|
1113 { |
|
1114 TTzRule trule( |
|
1115 startOfRule, endOfRule, |
|
1116 (TUint16)oldOffset, (TUint16)newOffset, (TMonth)aRuleDefs[i]->iMonth, (TTzRuleDay)aRuleDefs[i]->iDayRule, |
|
1117 aRuleDefs[i]->iDayOfMonth, aRuleDefs[i]->iDayOfWeek, |
|
1118 timeReference, timeOfChange); |
|
1119 |
|
1120 aTzRules.AddRuleL(trule); |
|
1121 |
|
1122 } |
|
1123 } |
|
1124 } |
|
1125 |
|
1126 void CTzDbRuleSet::FetchRuleDefinitionsL(RArray<TTzRuleDefinition*>& aTzRuleDefinitions, RArray<TTzRuleUse*>& aTzRuleUses, TInt aStartYear, TInt aEndYear) const |
|
1127 { |
|
1128 TInt ruleUseCount = iPersistedEntity.iNumberOfRuleUses; |
|
1129 TTzRuleUse* truleUse(NULL); |
|
1130 TTzRuleDefinition* truleDef(NULL); |
|
1131 for (TInt i = 0; i < ruleUseCount; i++) |
|
1132 { |
|
1133 truleUse = const_cast<TTzRuleUse*>(&iReadOnlyTzDb.GetTRuleUse(iPersistedEntity.iOffsetsToRuleUses[i])); |
|
1134 |
|
1135 // intersect rule use with (startYear,endYear) period |
|
1136 if ( (truleUse->iFromYear <= aEndYear) && (truleUse->iUntilYear >= aStartYear) ) |
|
1137 { |
|
1138 // Found one rule use valid during the years of interest - fetch rule definition. |
|
1139 // For every year, check if it occurs within (aStartTime,aEndTime) |
|
1140 truleDef = const_cast<TTzRuleDefinition*>(&iReadOnlyTzDb.GetTRuleDefinition(truleUse->iOffsetToRuleDefinition)); |
|
1141 // check that the rule definition has valid data. leave if the data is not valid, as it would mean that the database is corrupt |
|
1142 User::LeaveIfError(CTzHelpers::Validate((const TTzRuleDefinition&)*truleDef)); |
|
1143 |
|
1144 // Add rule definition ptr to array |
|
1145 aTzRuleDefinitions.Append(truleDef); |
|
1146 // Add rule use ptr to array |
|
1147 aTzRuleUses.Append(truleUse); |
|
1148 } |
|
1149 } |
|
1150 } |
|
1151 |
|
1152 void CTzDbRuleSet::ActualiseRuleDefinitionsL(CVTzActualisedRules& aActualisedRules, const RArray<TTzRuleDefinition*>& aTzRuleDefinitions, const RArray<TTzRuleUse*>& aTzRuleUses, TInt aUtcOffset, const TDateTime& aStartDateTime, const TDateTime& aEndDateTime, const TVTzActualisedRule& aDefaultRule) const |
|
1153 { |
|
1154 TInt startYear = aStartDateTime.Year(); |
|
1155 TInt endYear = (aActualisedRules.EndYear() < (TUint)aEndDateTime.Year()) ? aActualisedRules.EndYear() : aEndDateTime.Year(); |
|
1156 TInt rulesAddedSoFar = 0; |
|
1157 TInt yearOfFirstRule = endYear; |
|
1158 TInt count = aTzRuleDefinitions.Count(); |
|
1159 |
|
1160 TInt oldOffset = 0; // Arbitrarily set to zero. Required to create TTzRule. |
|
1161 |
|
1162 for (TInt i = 0; i < count; i++) |
|
1163 { |
|
1164 for (TInt year = (startYear > aTzRuleUses[i]->iFromYear) ? startYear : aTzRuleUses[i]->iFromYear ; (year <= endYear) && (year <= aTzRuleUses[i]->iUntilYear); year++) |
|
1165 { |
|
1166 TTzRule trule( |
|
1167 static_cast<TUint16>(startYear), static_cast<TUint16>(endYear), |
|
1168 static_cast<TUint16>(oldOffset), static_cast<TUint16>(aUtcOffset + aTzRuleDefinitions[i]->iStdTimeOffset),static_cast<TMonth>(aTzRuleDefinitions[i]->iMonth), static_cast<TTzRuleDay>(aTzRuleDefinitions[i]->iDayRule), |
|
1169 static_cast<TUint8>(aTzRuleDefinitions[i]->iDayOfMonth), static_cast<TUint8>(aTzRuleDefinitions[i]->iDayOfWeek), |
|
1170 static_cast<TTzTimeReference>(aTzRuleDefinitions[i]->iTimeReference), static_cast<TTzTimeReference>(aTzRuleDefinitions[i]->iTimeOfChange)); |
|
1171 |
|
1172 TVTzActualisedRule tActRule = trule.Actualise(year); |
|
1173 if ( (tActRule.iTimeOfChange < aEndDateTime) && (tActRule.iTimeOfChange >= aStartDateTime) ) |
|
1174 { |
|
1175 aActualisedRules.AddRuleL(tActRule); |
|
1176 // record the year of the first rule added |
|
1177 if (rulesAddedSoFar == 0) |
|
1178 { |
|
1179 yearOfFirstRule = year; |
|
1180 } |
|
1181 rulesAddedSoFar++; |
|
1182 } |
|
1183 } |
|
1184 } |
|
1185 |
|
1186 // In some cases we need to add a "default rule" to aRules. ("Default rule" |
|
1187 // means a rule with zero as DST offset and the start-time of the time-alignment |
|
1188 // as time-of-change). This default rule will be added if no rule exists for the |
|
1189 // first year of the time alignment. |
|
1190 if ( (rulesAddedSoFar == 0) || (yearOfFirstRule > startYear) ) |
|
1191 { |
|
1192 aActualisedRules.AddRuleL(aDefaultRule); |
|
1193 } |
|
1194 } |
|
1195 |
|
1196 //============================================================================================ |
|
1197 |
|
1198 TInt CTzHelpers::Validate(const TTzRuleDefinition& aRuleDefinition) |
|
1199 { |
|
1200 if (aRuleDefinition.iStdTimeOffset > KMaxDstOffset) |
|
1201 { |
|
1202 return KErrCorrupt; |
|
1203 } |
|
1204 |
|
1205 if (aRuleDefinition.iMonth > EDecember) |
|
1206 { |
|
1207 return KErrCorrupt; |
|
1208 } |
|
1209 |
|
1210 if (aRuleDefinition.iDayRule > KValidatedLastDayRule) // last element of enum TTzRuleDay |
|
1211 { |
|
1212 return KErrCorrupt; |
|
1213 } |
|
1214 |
|
1215 if (aRuleDefinition.iDayOfMonth > KMaxDayOfMonth) |
|
1216 { |
|
1217 return KErrCorrupt; |
|
1218 } |
|
1219 |
|
1220 if (aRuleDefinition.iDayOfWeek > ESunday) |
|
1221 { |
|
1222 return KErrCorrupt; |
|
1223 } |
|
1224 |
|
1225 if (aRuleDefinition.iTimeReference > KValidatedLastTimeReference) // last element of enum TTzTimeReference |
|
1226 { |
|
1227 return KErrCorrupt; |
|
1228 } |
|
1229 |
|
1230 if (aRuleDefinition.iTimeOfChange >= KMinutesInOneDay) |
|
1231 { |
|
1232 return KErrCorrupt; |
|
1233 } |
|
1234 |
|
1235 return KErrNone; |
|
1236 } |