tzservices/tzserver/Server/Source/tzdbentities.cpp
changeset 0 2e3d3ce01487
child 81 676b6116ca93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tzservices/tzserver/Server/Source/tzdbentities.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,1236 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "tzdbentities.h"
+#include "ReadOnlyTzDb.h"
+#include <vtzrules.h>
+
+/**
+This const must match the last TTzRuleDay enumeration in tzdefines.h.
+@internalComponent
+*/
+const TInt KValidatedLastDayRule = ETzDayInLastWeekOfMonth;
+
+/**
+This const must match the last TTzTimeReference enumeration in tzdefines.h.
+@internalComponent
+*/
+const TInt KValidatedLastTimeReference = ETzWallTimeReference;
+
+//=============================================================================
+
+CTzDbStringsTable* CTzDbStringsTable::NewL(const TTzStringsTable& aRegionsTable)
+	{
+	CTzDbStringsTable* self = new(ELeave) CTzDbStringsTable(aRegionsTable);
+	return self;
+	}
+
+CTzDbStringsTable::CTzDbStringsTable(const TTzStringsTable& aRegionsTable)
+	: iPersistedEntity(aRegionsTable)
+	{
+	}
+
+TPtrC8 CTzDbStringsTable::GetStringL(TUint aReferenceToString)
+	{
+	const TInt KStringsBaseAddress = (TInt)&iPersistedEntity;
+	const TInt KLengthAddress = KStringsBaseAddress + aReferenceToString;
+	const TInt KStringAddress = KLengthAddress + 1; // length occupies 1 byte
+	TUint8 length = *(reinterpret_cast<TUint8*>(KLengthAddress));
+	TPtrC8 theString(reinterpret_cast<TUint8*>(KStringAddress),length);
+	return theString;
+	}
+
+//=============================================================================
+
+CTzDbRegionsTable* CTzDbRegionsTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionsTable& aRegionsTable)
+	{
+	CTzDbRegionsTable* self = new(ELeave) CTzDbRegionsTable(aReadOnlyTzDb, aRegionsTable);
+	return self;
+	}
+
+CTzDbRegionsTable::CTzDbRegionsTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionsTable& aRegionsTable)
+:	iReadOnlyTzDb(aReadOnlyTzDb), 
+	iPersistedEntity(aRegionsTable)
+	{
+	}
+
+//
+// Looks for a region given its name.
+// Returns the region wrapped in a CTzDbRegion object.
+// Returns NULL if region is not found
+//
+CTzDbRegion* CTzDbRegionsTable::FindRegionL(const TDesC8& aRegionName)
+	{
+	const TInt KRegionCount = iPersistedEntity.iNumberOfRegions;
+	TTzRegion* region(NULL);
+	TPtrC8 name;
+	TInt regionAddress = reinterpret_cast<TInt>(&iPersistedEntity) + sizeof(iPersistedEntity.iNumberOfRegions);
+	for (TInt i = 0; i < KRegionCount; i++, regionAddress += sizeof(TTzRegion))
+		{
+		region = reinterpret_cast<TTzRegion*>(regionAddress);
+		name.Set(iReadOnlyTzDb.GetStringL(region->iOffsetToRegionName));
+
+		// compare both strings
+		if (aRegionName.Compare(name) == 0) // found our region
+			{
+			return CTzDbRegion::NewL(iReadOnlyTzDb,*region);
+			}
+		}
+
+	// if it gets here, it means that the region has not been found
+	return NULL;
+	}
+
+//=============================================================================
+
+CTzDbRegionalZonesTable* CTzDbRegionalZonesTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionalZonesTable& aRegionalZonesTable)
+	{
+	CTzDbRegionalZonesTable* self = new(ELeave) CTzDbRegionalZonesTable(aReadOnlyTzDb, aRegionalZonesTable);
+	return self;
+	}
+
+CTzDbRegionalZonesTable::CTzDbRegionalZonesTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegionalZonesTable& aRegionalZonesTable)
+:	iReadOnlyTzDb(aReadOnlyTzDb), 
+	iPersistedEntity(aRegionalZonesTable)
+	{
+	}
+
+const TTzRegionalZoneIndex& CTzDbRegionalZonesTable::GetTRegionalZoneIndex(TUint aReference)
+	{
+	return * reinterpret_cast<TTzRegionalZoneIndex*> (aReference + reinterpret_cast<TInt>(&iPersistedEntity));
+	}
+
+//=============================================================================
+
+CTzDbZonesTable* CTzDbZonesTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZonesTable& aZonesTable, TInt aZonesDataBaseAddress)
+	{
+	CTzDbZonesTable* self = new(ELeave) CTzDbZonesTable(aReadOnlyTzDb, aZonesTable, aZonesDataBaseAddress);
+	return self;
+	}
+
+CTzDbZonesTable::CTzDbZonesTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZonesTable& aZonesTable, TInt aZonesDataBaseAddress)
+:	iReadOnlyTzDb(aReadOnlyTzDb), 
+	iPersistedEntity(aZonesTable),
+	iZonesDataBaseAddress(aZonesDataBaseAddress)
+	{
+	}
+
+CTzDbZone* CTzDbZonesTable::GetZoneL(TUint aReference)
+	{
+	return CTzDbZone::NewL(iReadOnlyTzDb, GetTZone(aReference));
+	}
+
+TTzZone& CTzDbZonesTable::GetTZone(TUint aReference)
+	{
+	return *reinterpret_cast<TTzZone*>(aReference + iZonesDataBaseAddress);
+	}
+
+//
+// Performs a binary search in the zones table, looking for the zone with the
+// supplied numeric ID.
+//
+// IMPORTANT: Assumes zones are sorted by LocationId in zones table.
+//
+CTzDbZone* CTzDbZonesTable::GetZoneByIdL(TUint aNumericId)
+	{
+	TTzZone* tzone(NULL);
+	const TInt KZoneCount = iPersistedEntity.iNumberOfZones;
+	TInt start = 0;
+	TInt end = KZoneCount - 1;
+	TInt mid;
+	TBool found = EFalse;
+	while(start <= end)
+		{
+		mid = (end + start) / 2;
+		tzone = &GetTZone(iPersistedEntity.iOffsetsToZones[mid]);
+		if (aNumericId < tzone->iLocationId)
+			{
+			end = mid - 1;
+			}
+		else if (aNumericId == tzone->iLocationId)
+			{ 
+			// found our zone
+			found = ETrue;
+			break;
+			}
+		else
+			{
+			start = mid + 1;
+			}
+		}
+
+	if (found)
+		{
+		return CTzDbZone::NewL(iReadOnlyTzDb, *tzone);
+		}
+	else
+		{
+		return NULL;	
+		}
+	}
+
+//=============================================================================
+
+CTzDbLinksTable* CTzDbLinksTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzLinksTable& aLinksTable)
+	{
+	CTzDbLinksTable* self = new(ELeave) CTzDbLinksTable(aReadOnlyTzDb, aLinksTable);
+	return self;
+	}
+
+CTzDbLinksTable::CTzDbLinksTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzLinksTable& aLinksTable)
+:	iReadOnlyTzDb(aReadOnlyTzDb), 
+	iPersistedEntity(aLinksTable)
+	{
+	}
+
+CTzDbZone* CTzDbLinksTable::FindZoneL(const TDesC8& aLinkName)
+	{
+	const TInt KLinkCount = iPersistedEntity.iNumberOfLinks;
+	TPtrC8 name;
+	TTzLink* link(NULL);
+	TInt linkAddress = reinterpret_cast<TInt>(&iPersistedEntity) + sizeof(iPersistedEntity.iNumberOfLinks);
+	for (TInt i = 0; i < KLinkCount; i++, linkAddress += sizeof(TTzLink))
+		{
+		link = reinterpret_cast<TTzLink*>(linkAddress);
+		name.Set(iReadOnlyTzDb.GetStringL(link->iOffsetToLinkName));
+		if (!name.CompareC(aLinkName))
+			{ // we found our link
+			return iReadOnlyTzDb.GetZoneL(link->iOffsetToZone);
+			}
+		}
+
+	// if it gets here, it means that the zone has not been found
+	return NULL;
+	}
+
+//=============================================================================
+
+CTzDbStdTimeAlignmentsTable* CTzDbStdTimeAlignmentsTable::NewL(const TTzStdTimeAlignmentsTable& aStdTimeAlignmentsTable)
+	{
+	CTzDbStdTimeAlignmentsTable* self = new(ELeave) CTzDbStdTimeAlignmentsTable(aStdTimeAlignmentsTable);
+	return self;
+	}
+
+CTzDbStdTimeAlignmentsTable::CTzDbStdTimeAlignmentsTable(const TTzStdTimeAlignmentsTable& aStdTimeAlignmentsTable)
+	: iPersistedEntity(aStdTimeAlignmentsTable)
+	{
+	}
+
+TTzStdTimeAlignment& CTzDbStdTimeAlignmentsTable::GetTStdTimeAlignment(TUint aReference)
+	{
+	return *reinterpret_cast<TTzStdTimeAlignment*>(aReference + (TInt)&iPersistedEntity);
+	}
+
+//=============================================================================
+
+CTzDbRuleSetsTable* CTzDbRuleSetsTable::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSetsTable& aRuleSetsTable)
+	{
+	CTzDbRuleSetsTable* self = new(ELeave) CTzDbRuleSetsTable(aReadOnlyTzDb, aRuleSetsTable);
+	return self;
+	}
+
+CTzDbRuleSetsTable::CTzDbRuleSetsTable(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSetsTable& aRuleSetsTable)
+	: iReadOnlyTzDb(aReadOnlyTzDb), iPersistedEntity(aRuleSetsTable)
+	{
+	}
+
+CTzDbRuleSet* CTzDbRuleSetsTable::GetRuleSetL(TUint aReference)
+	{
+	return CTzDbRuleSet::NewL(iReadOnlyTzDb, GetTRuleSet(aReference));
+	}
+
+TTzRuleSet& CTzDbRuleSetsTable::GetTRuleSet(TUint aReference)
+	{
+	return * reinterpret_cast<TTzRuleSet*>(aReference + (TInt)&iPersistedEntity);
+	}
+
+//=============================================================================
+
+CTzDbRuleUsesTable* CTzDbRuleUsesTable::NewL(const TTzRuleUsesTable& aRuleUsesTable)
+	{
+	CTzDbRuleUsesTable* self = new(ELeave) CTzDbRuleUsesTable(aRuleUsesTable);
+	return self;
+	}
+
+CTzDbRuleUsesTable::CTzDbRuleUsesTable(const TTzRuleUsesTable& aRuleUsesTable)
+	: iPersistedEntity(aRuleUsesTable)
+	{
+	}
+
+TTzRuleUse& CTzDbRuleUsesTable::GetTRuleUse(TUint aReference)
+	{
+	return * reinterpret_cast<TTzRuleUse*> (aReference + (TInt)&iPersistedEntity);
+	}
+
+//=============================================================================
+
+CTzDbRuleDefinitionsTable* CTzDbRuleDefinitionsTable::NewL(const TTzRuleDefinitionsTable& aRuleDefinitionsTable)
+	{
+	CTzDbRuleDefinitionsTable* self = new(ELeave) CTzDbRuleDefinitionsTable(aRuleDefinitionsTable);
+	return self;
+	}
+
+CTzDbRuleDefinitionsTable::CTzDbRuleDefinitionsTable(const TTzRuleDefinitionsTable& aRuleDefinitionsTable)
+	: iPersistedEntity(aRuleDefinitionsTable)
+	{
+	}
+
+const TTzRuleDefinition& CTzDbRuleDefinitionsTable::GetRuleDefinition(TUint aReference)
+	{
+	return * reinterpret_cast<TTzRuleDefinition*>(aReference + (TInt)&iPersistedEntity);
+	}
+
+//=============================================================================
+
+CTzDbRegion* CTzDbRegion::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegion& aRegion)
+	{
+	CTzDbRegion* self = new(ELeave) CTzDbRegion(aReadOnlyTzDb,aRegion);
+	return self;
+	}
+
+CTzDbRegion::CTzDbRegion(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRegion& aRegion)
+:	iReadOnlyTzDb(aReadOnlyTzDb),
+	iPersistedEntity(aRegion)
+	{
+	}
+
+CTzDbZone* CTzDbRegion::FindZoneL(TUint aCityNameReference)
+	{
+	TTzRegionalZoneIndex* zoneIndex = const_cast<TTzRegionalZoneIndex*>(&iReadOnlyTzDb.GetTRegionalZoneIndex(iPersistedEntity.iOffsetToRegionalZoneIndex));
+	const TInt KZoneCount = zoneIndex->iNumberOfZones;
+	TTzZone* tzone(NULL);
+	for (TInt i = 0; i < KZoneCount; i++)
+		{
+		tzone = const_cast<TTzZone*>(&iReadOnlyTzDb.GetTZone(zoneIndex->iOffsetsToZones[i]));
+		if (tzone->iOffsetToZoneName == aCityNameReference)
+			{ // found our zone
+			return CTzDbZone::NewL(iReadOnlyTzDb,*tzone);
+			}
+		}
+
+	// if it gets here, it means that the zone has not been found
+	return NULL;
+	}
+
+CTzDbZone* CTzDbRegion::FindZoneL(const TDesC8& aCityName)
+	{
+	TTzZone* tzone(NULL);
+	TTzRegionalZoneIndex* zoneIndex = const_cast<TTzRegionalZoneIndex*>(&iReadOnlyTzDb.GetTRegionalZoneIndex(iPersistedEntity.iOffsetToRegionalZoneIndex));
+	const TInt KZoneCount = zoneIndex->iNumberOfZones;
+	TPtrC8 name;
+
+	TBool found = EFalse;
+	TInt start = 0;
+	TInt end = KZoneCount - 1;
+	TInt mid;
+
+	// perform a binary search for aCityName among the zones listed in the zone index. This assumes
+	// that zones are sorted alphabetically in the zone index.
+	while (start <= end)
+		{
+		mid = (end + start) / 2;
+		tzone = const_cast<TTzZone*>(&iReadOnlyTzDb.GetTZone(zoneIndex->iOffsetsToZones[mid]));
+		
+		// compare this zone's name with the name we've been given as a parameter
+		// use strict comparison method Compare, as CompareC may cause the search to fail:
+		// for example, Stanley will come BEFORE St_Helens using the standard collation method in Symbian OS,
+		// but it will have been placed AFTER St_Helens by std::sort in he TZ Compiler. This would result
+		// in this binary search to fail.
+		name.Set(iReadOnlyTzDb.GetStringL(tzone->iOffsetToZoneName));
+		if (aCityName.Compare(name) < 0)
+			{
+			end = mid - 1;
+			}
+		else if (aCityName.Compare(name) == 0) 
+			{ // found our zone
+			found = ETrue;
+			break;
+			}
+		else if (aCityName.Compare(name) > 0)
+			{
+			start = mid + 1;
+			}
+		}
+
+	if (found)
+		{
+		return CTzDbZone::NewL(iReadOnlyTzDb,*tzone);
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+//=============================================================================
+
+CTzDbZone* CTzDbZone::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZone& aZone)
+	{
+	CTzDbZone* self = new(ELeave) CTzDbZone(aReadOnlyTzDb,aZone);
+	return self;
+	}
+
+CTzDbZone::CTzDbZone(CReadOnlyTzDb& aReadOnlyTzDb, const TTzZone& aZone)
+:	iReadOnlyTzDb(aReadOnlyTzDb),
+	iPersistedEntity(aZone)
+	{
+	}
+
+void CTzDbZone::GetRulesL(CTzRules& aRules)
+	{	
+	// start and end years of interest
+	TInt firstYearOfInterest = aRules.StartYear();
+	TInt lastYearOfInterest = aRules.EndYear();
+
+	// record last instant of end year, in order to see if we need to get another time alignment
+	TDateTime endDateTimeOfInterest(lastYearOfInterest,EDecember,30,23,59,59,0);
+	TTime endTimeOfInterest(endDateTimeOfInterest);
+
+	// initialise start time to beginning of startYear (UTC)
+	TDateTime startDateTime(firstYearOfInterest,EJanuary,0,0,0,0,0);
+	TTime startTime(startDateTime);
+	TTime staEndTime;
+	TDateTime staEndDateTime;
+	TTzTimeReference staTimeReference(ETzUtcTimeReference);
+
+	// the following variables are used to iterate through the list of standard time alignments for this location
+	TInt taCount = iPersistedEntity.iNumberOfStdTimeAlignments;
+	TInt tmpOffset;
+	TTzStdTimeAlignment* ta(NULL);
+	TTzStdTimeAlignment* prevTa(NULL);
+	CTzDbStdTimeAlignment* sta = NULL;
+
+	// the standard time offset at the beginning of the period of interest has to be set in aTzRules
+	TBool initialOffsetHasBeenSet = EFalse;
+	
+	// Iterate through std time alignments until we find the one that contains our date of interest.
+	// Get the rules for this time alignment, up to the end of the time alignment or the end of our 
+	// period of interest (whichever comes first).
+	// If the period of interest is covered by only one time alignment, finish and return.
+	// If the period of interest is covered by more than one time alignment, repeat procedure with 
+	// next time alignment(s) until we reach the end of the period of interest
+	for (TInt i = 0; (i < taCount) && (startTime < endTimeOfInterest ); i++)
+		{
+		// get a standard time alignment
+
+		prevTa = ta; // this will be needed to eventually wrap the time alignment in a CTzDbStdTimeAlignment object
+		tmpOffset = iPersistedEntity.iOffsetsToTimeAlignments[i];
+		ta = const_cast<TTzStdTimeAlignment*>(&iReadOnlyTzDb.GetTStdTimeAlignment(tmpOffset));
+
+		// check if our time of interest is within this time alignment
+		if (IsTimeInStdTimeAlignment(*ta,	startDateTime.Year(),
+											startDateTime.Month(),
+											startDateTime.Day(),
+											startDateTime.Hour(),
+											startDateTime.Minute(),
+											staTimeReference) )
+			{
+			// wrap the time alignment in a CTzDbStdTimeAlignment object
+			sta = CTzDbStdTimeAlignment::NewL(iReadOnlyTzDb,*ta,prevTa);
+			if (sta)
+				{
+				CleanupStack::PushL(sta); // push #1 - sta
+				
+				if (initialOffsetHasBeenSet == EFalse)
+					{
+					aRules.SetInitialStdTimeOffset(ta->iUtcOffset);
+					initialOffsetHasBeenSet = ETrue;
+					}
+					
+				// staStartDateTime, staEndTime are passed by reference and their values
+				// are updated in GetRulesL
+				sta->GetRulesL(aRules,startDateTime,staEndDateTime);
+
+				// The time reference to calculate the start of the next time alignment is the time reference
+				// in which the end time of this time alignment is expressed 
+				staTimeReference = static_cast<TTzTimeReference>(sta->UntilTimeReference());
+				CleanupStack::PopAndDestroy(sta); // pop #1 - sta
+
+				staEndTime = staEndDateTime;
+				if (staEndTime == Time::MaxTTime())
+					{
+					startTime = staEndTime; // this will cause loop to finish
+					}
+				else
+					{
+					// move just after end of time alignment
+					startTime = staEndTime + static_cast<TTimeIntervalSeconds>(1);
+					startDateTime = startTime.DateTime();
+					}
+				}
+			} // if IsTimeInStdTimeAlignment(...)
+		} // for
+			
+	}
+	
+TBool CTzDbZone::IsTimeInStdTimeAlignment(const TTzStdTimeAlignment& aStdTa, TInt aYear, TInt aMonth, TInt aDay, TInt aHour, TInt aMinute, TTzTimeReference aTimeRef)
+	{
+	TInt found = EFalse;
+
+	if (aYear > (TInt)KMaxTUint16)
+		{
+		aYear = KMaxTUint16; // KMaxTUint16 (0xFFFF) is the value given to year when the end of a time alignment is unknown
+		}
+
+	if (aStdTa.iUntilYear > aYear)
+		{
+		found = ETrue;
+		}
+	else if (aStdTa.iUntilYear == aYear)
+		{
+		if ( (aStdTa.iUntilMonth > aMonth) || (aStdTa.iUntilMonth == KMaxTUint8) )
+			{
+			found = ETrue;
+			}
+		else if (aStdTa.iUntilMonth == aMonth)
+			{
+			// evaluate the day and time the time alignment ends 
+			// and see if the received time falls in or out of the t.a.
+			TTime ourTime;
+
+			if (aYear >= (TInt)KMaxTUint16)
+				{
+				ourTime = Time::MaxTTime();
+				}
+			else
+				{
+				TDateTime ourDateTime(aYear,
+									(TMonth)aMonth,
+									aDay,
+									aHour,
+									aMinute,
+									0,
+									0);
+
+				ourTime = ourDateTime;
+
+				// convert ourTime to UTC
+				if (aTimeRef == ETzStdTimeReference)
+					{
+					ourTime -= static_cast<TTimeIntervalMinutes>(aStdTa.iUtcOffset);
+					}
+				}
+
+			TTime endTime;
+			if (aStdTa.iUntilYear == KMaxTUint16)
+				{
+				endTime = Time::MaxTTime();
+				}
+			else
+				{
+				TDateTime endDateTime(aStdTa.iUntilYear,
+									(TMonth)aStdTa.iUntilMonth,
+									aStdTa.iUntilDayOfMonth,
+									(aStdTa.iUntilTimeInMinutes / 60),
+									(aStdTa.iUntilTimeInMinutes % 60),
+									0,
+									0);
+
+				endTime = endDateTime;
+
+				// convert endTime to UTC
+				if (aTimeRef == ETzStdTimeReference)
+					{
+					endTime -= static_cast<TTimeIntervalMinutes>(aStdTa.iUtcOffset);
+					}
+				}
+			
+			// and finally compare both times
+			if (endTime >= ourTime)
+				{
+				found = ETrue;
+				}
+			}
+		} // else if (aStdTa->iUntilYear == aYear)
+
+	return found;
+	}
+//
+// Traverses the collection of Std Time Alignments for the current zone, looking for the one that 
+// matches the given time.
+// Returns a CTzDbStdTimeAlignment object.
+//
+CTzDbStdTimeAlignment* CTzDbZone::FindStdTimeAlignmentL(TInt aYear, TInt aMonth, TInt aDay, TInt aHour, TInt aMinute, const TTzTimeReference aTimeRef)
+	{
+	TTzStdTimeAlignment* ta(NULL);
+	TTzStdTimeAlignment* prevTa(NULL);
+	TInt taCount = iPersistedEntity.iNumberOfStdTimeAlignments;
+	TBool found = EFalse;
+	TInt tmpOffset = 0;
+	for (TInt i = 0; (i < taCount) && (!found); i++)
+		{
+		prevTa = ta;
+		tmpOffset = iPersistedEntity.iOffsetsToTimeAlignments[i];
+		ta = const_cast<TTzStdTimeAlignment*>(&iReadOnlyTzDb.GetTStdTimeAlignment(tmpOffset));
+		
+		found = IsTimeInStdTimeAlignment(*ta,aYear,aMonth,aDay,aHour,aMinute,aTimeRef);
+		}
+		
+	if (found)
+		{
+		return CTzDbStdTimeAlignment::NewL(iReadOnlyTzDb, *ta, prevTa);
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+HBufC8* CTzDbZone::GetFullZoneNameLC()
+	{
+	HBufC8* fullName = HBufC8::NewL(KMaxTimeZoneIdSize);
+	CleanupStack::PushL(fullName);
+	TPtr8 fullNamePtr(fullName->Des() );
+	fullNamePtr.Append(iReadOnlyTzDb.GetStringL(iPersistedEntity.iOffsetToRegionName));
+	if (fullNamePtr.Length() > 0)
+		{
+		// if the region name is empty (e.g. zone "CET"), don't add the slash
+		fullNamePtr.Append('/');
+		}
+	fullNamePtr.Append(iReadOnlyTzDb.GetStringL(iPersistedEntity.iOffsetToZoneName));
+
+	return fullName;
+	}
+
+//========================================================================
+
+CTzDbStdTimeAlignment* CTzDbStdTimeAlignment::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzStdTimeAlignment& aTimeAlignment, TTzStdTimeAlignment* aPrevTimeAlignment)
+	{
+	CTzDbStdTimeAlignment* self = new(ELeave) CTzDbStdTimeAlignment(aReadOnlyTzDb,aTimeAlignment,aPrevTimeAlignment);
+	return self;		
+	}
+
+CTzDbStdTimeAlignment::CTzDbStdTimeAlignment(CReadOnlyTzDb& aReadOnlyTzDb, 
+							const TTzStdTimeAlignment& aTimeAlignment, TTzStdTimeAlignment* aPrevTimeAlignment)
+	: iReadOnlyTzDb(aReadOnlyTzDb)
+	{
+	iPersistedEntity = aTimeAlignment;
+	iPrevTimeAlignment = aPrevTimeAlignment;
+	}
+
+CTzDbStdTimeAlignment::~CTzDbStdTimeAlignment()
+	{
+	}
+
+void CTzDbStdTimeAlignment::GetRulesL(CTzRules& aRules, const TDateTime& aStartDateTime, TDateTime& aEndDateTime)
+	{
+	// get the ruleSet for this time alignment
+	CTzDbRuleSet* ruleSet = iReadOnlyTzDb.GetRuleSetL(iPersistedEntity.iOffsetToRuleSet);
+	if (ruleSet)
+		{
+		CleanupStack::PushL(ruleSet); // PUSH #1 - RULESET
+
+		// get end time of time alignment
+		TTime endTime;
+		CalculateEndTime(endTime);
+		if (endTime == Time::MaxTTime())
+			{
+			aEndDateTime.SetYear(KMaxTUint16);
+			}
+		else
+			{
+			aEndDateTime = endTime.DateTime();
+			}
+	
+		TInt firstYearOfInterest = (aRules.StartYear() >= aStartDateTime.Year()) ? aRules.StartYear() : aStartDateTime.Year();
+		TInt lastYearOfInterest  = (aRules.EndYear() <= aEndDateTime.Year()) ? aRules.EndYear() : aEndDateTime.Year();
+		CTzRules* newRules = CTzRules::NewL(firstYearOfInterest, lastYearOfInterest);
+		CleanupStack::PushL(newRules); // PUSH #2 - NEWRULES
+		
+		ruleSet->GetRulesL(*newRules,iPersistedEntity.iUtcOffset,aStartDateTime,aEndDateTime);
+		
+		// the new rules obtained for the current std time alignment must be merged into 
+		// the global rule collection
+		AddRulesToCollectionL(aRules,*newRules);
+	
+		CleanupStack::PopAndDestroy(2, ruleSet); // POP #2,#1 - NEWRULES, RULESET
+		}
+	}
+
+void CTzDbStdTimeAlignment::AddRulesToCollectionL(CTzRules& aRuleCollection, CTzRules& aNewRules)
+	{
+	TTzRule* tRule(NULL);
+	TVTzActualisedRule tActRule;
+	TInt count = aNewRules.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		TBool ruleAdded = EFalse;
+		tRule = &(aNewRules[i]);
+		TInt basicRuleFromYear = tRule->iFrom.iTime.DateTime().Year();
+		TInt basicRuleToYear = tRule->iTo.iTime.DateTime().Year();
+		
+		if ( (iPrevTimeAlignment != NULL) 
+			&& (basicRuleFromYear <= iPrevTimeAlignment->iUntilYear)
+			&& (basicRuleToYear >= iPrevTimeAlignment->iUntilYear) )
+			{ // the rule is in effect during the first year of the time alignment
+			// actualise rule for this year and remove it if it falls outside the time alignment
+			tActRule = tRule->Actualise(iPrevTimeAlignment->iUntilYear);
+			
+			// work out start time of time alignment (i.e. end time of the prev. alignment)
+				
+			TDateTime staStartDateTime(	iPrevTimeAlignment->iUntilYear,
+										(TMonth)iPrevTimeAlignment->iUntilMonth,
+										iPrevTimeAlignment->iUntilDayOfMonth,
+										iPrevTimeAlignment->iUntilTimeInMinutes/60, // hour
+										iPrevTimeAlignment->iUntilTimeInMinutes%60, // minute
+										0,0); // second, ms
+			
+			// make sure times are expressed in the same reference (UTC or Local)
+			if (tActRule.iTimeReference != iPrevTimeAlignment->iUntilTimeReference)
+				{			
+				if (iPrevTimeAlignment->iUntilTimeReference == ETzWallTimeReference)
+					{ // convert sta start time to UTC
+					TTime staTime(staStartDateTime);
+					staTime -= (TTimeIntervalMinutes)(iPrevTimeAlignment->iUtcOffset);
+					staStartDateTime = staTime.DateTime();
+					}
+				else if (iPrevTimeAlignment->iUntilTimeReference == ETzUtcTimeReference)
+					{ // convert time of change to UTC
+					tActRule.iTimeOfChange -= (TTimeIntervalMinutes)tRule->iOldLocalTimeOffset;
+					}
+				}
+			
+			// add rule to collection only if its time of change falls within the time alignment
+			if (tActRule.iTimeOfChange >= staStartDateTime)
+				{
+				aRuleCollection.AddRuleL(*tRule);
+				ruleAdded = ETrue;
+				}
+			else 
+				{
+				TDateTime tActRuleDt = tActRule.iTimeOfChange.DateTime();
+				/*
+				Fix for INC117764:
+				Update the rule's month and daytime information only if the rule starts and ends in the same year
+				otherwise just add them to the collection.
+				For example:
+				Iqaluit rules:
+				-6:00	Canada	C%sT	2000 Oct 29 2:00
+				-5:00	Canada	E%sT
+
+				Rule	Canada	1974	2006	-	Oct	lastSun	2:00	0	S
+				Rule	Canada	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
+				Rule	Canada	2007	max	-	Mar	Sun>=8	2:00	1:00	D
+				Rule	Canada	2007	max	-	Nov	Sun>=1	2:00	0	S
+				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
+				should be alternating between October and April till 2006.
+				*/
+				if ((tActRuleDt.Year() == staStartDateTime.Year()) && (basicRuleFromYear == basicRuleToYear) )
+					{
+					tRule->iMonth = staStartDateTime.Month();
+					tRule->iDayOfMonth = staStartDateTime.Day();
+					tRule->iDayRule = ETzFixedDate;
+					aRuleCollection.AddRuleL(*tRule);
+					ruleAdded = ETrue;
+					}
+				else if (tActRuleDt.Year() == staStartDateTime.Year())
+					{
+					aRuleCollection.AddRuleL(*tRule);
+					ruleAdded = ETrue;	
+					}
+				}
+			}
+		else if (  
+					(tRule->iFrom.iTime.DateTime().Year() <= iPersistedEntity.iUntilYear)
+				 	&&(tRule->iTo.iTime.DateTime().Year() >= iPersistedEntity.iUntilYear) 
+				 )
+			{ 
+			// the rule is in effect during the last year of the time alignment
+			tActRule = tRule->Actualise(iPersistedEntity.iUntilYear);
+			
+			TDateTime staEndDateTime(iPersistedEntity.iUntilYear, (TMonth)iPersistedEntity.iUntilMonth, 
+									 iPersistedEntity.iUntilDayOfMonth, 
+									 iPersistedEntity.iUntilTimeInMinutes / 60, // hour
+									 iPersistedEntity.iUntilTimeInMinutes % 60, // minute
+									 0,0); // second, ms
+									 
+			if (tActRule.iTimeReference != iPersistedEntity.iUntilTimeReference)
+				{
+				if (iPersistedEntity.iUntilTimeReference == ETzWallTimeReference)
+					{
+					TTime staTime(staEndDateTime);
+					staTime -= (TTimeIntervalMinutes)iPersistedEntity.iUtcOffset;
+					staEndDateTime = staTime.DateTime();
+					}
+				else if (iPersistedEntity.iUntilTimeReference == ETzUtcTimeReference)
+					{
+					tActRule.iTimeOfChange -= (TTimeIntervalMinutes)tRule->iOldLocalTimeOffset;
+					}
+				}
+				
+			// add rule to collection only if its time of change falls withing the time alignment
+			if (tActRule.iTimeOfChange < staEndDateTime)
+				{
+				aRuleCollection.AddRuleL(*tRule);
+				ruleAdded = ETrue;
+				}
+			}
+		else
+			{
+			// no doubt that the rule falls within the time alignment
+			aRuleCollection.AddRuleL(*tRule);
+			ruleAdded = ETrue;
+			}
+		/*
+		Fix for INC117764:
+		Updating the default rule for a year if any new rule overlaps with the default rule.(Default rules start and end at same time)
+		The offsets are updated if default rule and newly added rule start during same time and newly added rule month occurs before
+		the default rule month.
+		*/
+		if( ruleAdded )
+			{
+			if(basicRuleFromYear != basicRuleToYear)
+				{
+				TInt ruleCount = aRuleCollection.Count() - 2;								
+				for(TInt loop = ruleCount;loop >= 0; --loop)
+					{
+					TTzRule prevAddedRule = aRuleCollection[loop];
+					//check that we do not update a winter rule using a summer rule and vice versa					
+					//Summer rules start before July and winter rules after
+					if(tRule->iMonth < EJuly && prevAddedRule.iMonth > EJuly)
+						{
+						continue;	
+						}
+					if(tRule->iMonth > EJuly && prevAddedRule.iMonth < EJuly)
+						{
+						continue;	
+						}
+					if(basicRuleFromYear > prevAddedRule.iFrom.iTime.DateTime().Year())
+						{
+						//no need to check beyond the newly added rules start year.
+						break;	
+						}					
+					if((tRule->iFrom == prevAddedRule.iFrom) &&
+					 (prevAddedRule.iFrom == prevAddedRule.iTo) && 
+					 (tRule->iMonth < prevAddedRule.iMonth))
+						{
+						prevAddedRule.iOldLocalTimeOffset = tRule->iOldLocalTimeOffset;
+						prevAddedRule.iNewLocalTimeOffset = tRule->iNewLocalTimeOffset;
+						aRuleCollection.RemoveRule(loop);
+						aRuleCollection.AddRuleL(prevAddedRule);
+						}
+					}	
+				}		
+			}
+		} // for
+	}
+
+TInt CTzDbStdTimeAlignment::UtcOffset()
+	{
+	return iPersistedEntity.iUtcOffset;	
+	}
+
+TUint CTzDbStdTimeAlignment::RuleSetReference()	
+	{
+	return iPersistedEntity.iOffsetToRuleSet;	
+	}
+
+TInt CTzDbStdTimeAlignment::UntilYear()			
+	{
+	return iPersistedEntity.iUntilYear;		
+	}
+
+TInt CTzDbStdTimeAlignment::UntilMonth()			
+	{
+	return iPersistedEntity.iUntilMonth;		
+	}
+
+TInt CTzDbStdTimeAlignment::UntilDay()	
+	{
+	return iPersistedEntity.iUntilDayOfMonth;		
+	}
+
+TInt CTzDbStdTimeAlignment::UntilTimeInMinutes()	
+	{
+	return iPersistedEntity.iUntilTimeInMinutes;
+	}
+
+TInt CTzDbStdTimeAlignment::UntilTimeReference()
+	{
+	return iPersistedEntity.iUntilTimeReference;
+	}	
+	
+//
+// Calculate End Time of TimeAlignment (UTC)
+//
+void CTzDbStdTimeAlignment::CalculateEndTime(TTime& aEndTime)
+	{
+	TInt endYear;
+	TInt endMonth;
+	TInt endDay;
+	TInt endHour;
+	TInt endMinute;
+	TInt endSecond = 0;
+	TInt endMicrosecond = 0;
+	
+	if (iPersistedEntity.iUntilYear == KMaxTUint16)
+		{
+		aEndTime = Time::MaxTTime();
+		}
+	else
+		{
+		
+		endYear = iPersistedEntity.iUntilYear;
+		endMonth = iPersistedEntity.iUntilMonth; if (endMonth > EDecember) endMonth = EJanuary;
+		endDay = iPersistedEntity.iUntilDayOfMonth; if (endDay > 31) endDay = 0;
+		if (iPersistedEntity.iUntilTimeInMinutes == KMaxTUint16)
+			{
+			endHour = endMinute = 0;
+			}
+		else
+			{
+			endHour = iPersistedEntity.iUntilTimeInMinutes / 60;
+			endMinute = iPersistedEntity.iUntilTimeInMinutes % 60;
+			}
+
+		TDateTime endDateTime(endYear,(TMonth)endMonth,endDay,endHour,endMinute,endSecond,endMicrosecond);
+		aEndTime = endDateTime;
+
+		// convert time to UTC
+		TTzTimeReference taTimeReference(static_cast<TTzTimeReference>(iPersistedEntity.iUntilTimeReference) );
+		if (taTimeReference == ETzStdTimeReference)
+			{
+			aEndTime -= static_cast<TTimeIntervalMinutes>(iPersistedEntity.iUtcOffset);
+			}		
+
+		// aEndTime is, at this point, the beginning of the the next Std Time Alignment
+		aEndTime -= static_cast<TTimeIntervalSeconds>(1);
+		}	
+	}
+
+//
+// Calculate Start Time of TimeAlignment (UTC)
+//
+void CTzDbStdTimeAlignment::CalculateStartTime(TTime& aStartTime)
+  	{
+  	TInt startYear;
+  	TInt startMonth;
+  	TInt startDay;
+  	TInt startHour;
+  	TInt startMinute;
+  	TInt startSecond = 0;
+  	TInt startMicrosecond = 0;
+  	
+  	if (iPrevTimeAlignment == NULL)
+  		{
+  		aStartTime = 0;
+  		}
+  	else
+  		{
+  		startYear = iPrevTimeAlignment->iUntilYear;
+  		startMonth = iPrevTimeAlignment->iUntilMonth; if (startMonth == (TInt)KMaxTUint8) startMonth = EJanuary;
+  		startDay = iPrevTimeAlignment->iUntilDayOfMonth; if (startDay == (TInt)KMaxTUint8) startDay = 0;
+  		if (iPrevTimeAlignment->iUntilTimeInMinutes == KMaxTUint16)
+  			{
+  			startHour = startMinute = 0;
+  			}
+  		else
+  			{
+  			startHour = iPrevTimeAlignment->iUntilTimeInMinutes / 60;
+  			startMinute = iPrevTimeAlignment->iUntilTimeInMinutes % 60;
+  			}
+  
+  		TDateTime startDateTime(startYear,(TMonth)startMonth,startDay,startHour,startMinute,startSecond,startMicrosecond);
+  		aStartTime = startDateTime;
+		// convert time to UTC
+		TTzTimeReference taTimeReference(static_cast<TTzTimeReference>(iPersistedEntity.iUntilTimeReference) );
+		if (taTimeReference == ETzStdTimeReference)
+			{
+			aStartTime -= static_cast<TTimeIntervalMinutes>(iPersistedEntity.iUtcOffset);
+			}		
+  		}		
+  	}
+	
+//========================================================================
+
+CTzDbRuleSet* CTzDbRuleSet::NewL(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSet& aRuleSet)
+	{
+	CTzDbRuleSet* self = new(ELeave) CTzDbRuleSet(aReadOnlyTzDb,aRuleSet);
+	return self;	
+	}
+
+
+CTzDbRuleSet::CTzDbRuleSet(CReadOnlyTzDb& aReadOnlyTzDb, const TTzRuleSet& aRuleSet)
+	: iReadOnlyTzDb(aReadOnlyTzDb),
+	iPersistedEntity(aRuleSet)
+	{
+	}
+
+//
+// Gets the encoded rules for the current standard time alignment, between aStartDateTime and aEndDateTime
+//
+void CTzDbRuleSet::GetRulesL(CTzRules& aTzRules, TInt aUtcOffset, const TDateTime& aStartDateTime, const TDateTime& aEndDateTime) const
+	{	
+	TInt startYear = aStartDateTime.Year();
+	// the last year we are interested in is the earliest of the following:
+	// 		1) the last year of the CTzRules
+	//		2) the year of aEndDateTime (the end of the invoking std time alignment)
+	
+	TInt endYear = (aEndDateTime.Year() < aTzRules.EndYear()) 
+		? aEndDateTime.Year() : aTzRules.EndYear();
+	const TDateTime rulesEndDateTime(aTzRules.EndYear(), EDecember, 30, 0,0,0,0);
+	const TDateTime& endDateTime = (aEndDateTime.Year() <= aTzRules.EndYear())
+		? aEndDateTime : rulesEndDateTime;
+	
+	RArray<TTzRuleDefinition*> ruleDefs;
+	CleanupClosePushL(ruleDefs); // PUSH #1
+	RArray<TTzRuleUse*> ruleUses;
+	CleanupClosePushL(ruleUses); // PUSH #2
+	
+	FetchRuleDefinitionsL(ruleDefs,ruleUses,startYear,endYear);
+
+	// fetch rules for previous year (these will be needed to work out the "Old Offset" field of 
+	// the first rule in aStartYear	
+	TInt initialLocalTimeOffset = GetLocalTimeOffsetAtEndOfYearL(startYear-1,aUtcOffset);
+		
+	// convert rule definitions (together with rule uses) to TTzRules and add them to aTzRules
+	
+	CompleteRulesAndAddToCollectionL(aTzRules,ruleDefs,ruleUses,aUtcOffset,initialLocalTimeOffset,aStartDateTime,endDateTime);
+	
+	CleanupStack::PopAndDestroy(2,&ruleDefs); // POP #2,#1 - ruleUses, ruleDefs
+	}
+
+TInt CTzDbRuleSet::GetLocalTimeOffsetAtEndOfYearL(TInt aYear, TInt aUtcOffset) const
+	{
+	RArray<TTzRuleDefinition*> ruleDefs;
+	CleanupClosePushL(ruleDefs);
+	RArray<TTzRuleUse*> ruleUses;
+	CleanupClosePushL(ruleUses);
+	
+	TDateTime startDateTime(aYear,EJanuary,0,0,0,0,0);
+	TDateTime endDateTime(aYear,EDecember,30,23,59,59,0);
+	
+	FetchRuleDefinitionsL(ruleDefs,ruleUses,aYear,aYear);
+	
+	CVTzActualisedRules* actRules = CVTzActualisedRules::NewL(aYear,aYear);
+	CleanupStack::PushL(actRules);
+	TVTzActualisedRule tDefaultRule(startDateTime,aUtcOffset,ETzUtcTimeReference);
+	ActualiseRuleDefinitionsL(*actRules,ruleDefs,ruleUses,aUtcOffset,startDateTime,endDateTime,tDefaultRule);
+
+	TInt count = actRules->Count();
+	TInt finalOffset = (*actRules)[count-1].iNewOffset;
+		
+	CleanupStack::PopAndDestroy(3,&ruleDefs);
+	return finalOffset;
+	}
+
+
+void CTzDbRuleSet::CompleteRulesAndAddToCollectionL(
+					CTzRules& aTzRules, 
+					const RArray<TTzRuleDefinition*>& aRuleDefs, 
+					const RArray<TTzRuleUse*>& aRuleUses, 
+					TInt aUtcOffset, TInt aInitialLocalTimeOffset,
+					TDateTime aStart, TDateTime aEnd) const
+	{
+	TInt count = aRuleDefs.Count();
+	if (count != aRuleUses.Count())
+		{
+		User::Leave(KErrCorrupt);
+		}
+	
+	TTimeWithReference startOfAlignment(aStart,ETzUtcTimeReference);
+	TTimeWithReference endOfAlignment(aEnd,ETzUtcTimeReference);
+
+	//Keep track of changes to UTC offset
+	// even if there are no DST rules.
+	TTzRule trule(	
+				startOfAlignment, startOfAlignment,
+				(TUint16)aInitialLocalTimeOffset, (TUint16)aInitialLocalTimeOffset, EJanuary, ETzFixedDate,
+				0, 0, 
+				ETzUtcTimeReference, 
+				0);
+	aTzRules.AddRuleL(trule);		
+	//Calculate the new and old offsets for each rule.
+	TInt prevOffset = 0;
+	TInt maxOffset = 0;
+	for (TInt i = 0; i < count; i++)
+		{
+		TInt oldOffset = aInitialLocalTimeOffset;
+		TInt dstOffset = aRuleDefs[i]->iStdTimeOffset;
+		TInt newOffset = aUtcOffset + dstOffset;
+		//newoffset and oldoffset should always have a difference of dstoffset.
+		if (newOffset <= oldOffset )
+			{
+			//there are cases when dstoffset in the set of rules is same for few continuous rules
+			//in such cases, newoffset and oldoffset would have a difference of maxoffset.
+			if(prevOffset == dstOffset)
+				{
+				oldOffset =	aUtcOffset + maxOffset;		
+				}
+			else
+				{
+				oldOffset =	aUtcOffset + prevOffset;		
+				}				
+			}
+		else
+			//newoffset is more than oldoffset so maintain the difference with dstoffset.
+			{
+			oldOffset =	newOffset - dstOffset;							
+			}
+		prevOffset = dstOffset;		
+		//store maximum offset, to handle cases in which dstoffset in the set of rules
+		//is same for few continuous rules
+		if(dstOffset > maxOffset)
+			{
+			maxOffset = dstOffset;
+			}
+			
+		TUint16 timeOfChange = aRuleDefs[i]->iTimeOfChange;
+		TTzTimeReference timeReference = 
+			static_cast<TTzTimeReference>(aRuleDefs[i]->iTimeReference);
+
+		//
+
+		// Find the intersection of the date ranges:
+		//  use latest start year, earliest end year
+		TDateTime start = aStart;
+		TDateTime end = aEnd;
+		if(aRuleUses[i]->iFromYear > start.Year())
+			{
+			start = TDateTime(aRuleUses[i]->iFromYear,EJanuary,0,0,0,0,0);
+			}
+			
+		if(aEnd.Year() > aRuleUses[i]->iUntilYear)
+			{
+			end = TDateTime(aRuleUses[i]->iUntilYear,EDecember,30,23,59,59,0);
+			}
+			
+		TTimeWithReference startOfRule(start,ETzUtcTimeReference);
+		TTimeWithReference endOfRule(end,ETzUtcTimeReference);
+		if(endOfRule.iTime >= startOfRule.iTime)
+			{
+			TTzRule trule(	
+						startOfRule, endOfRule,
+						(TUint16)oldOffset, (TUint16)newOffset, (TMonth)aRuleDefs[i]->iMonth, (TTzRuleDay)aRuleDefs[i]->iDayRule,
+						aRuleDefs[i]->iDayOfMonth, aRuleDefs[i]->iDayOfWeek, 
+						timeReference, timeOfChange);				 
+
+			aTzRules.AddRuleL(trule);
+	
+			}
+		}	
+	}
+
+void CTzDbRuleSet::FetchRuleDefinitionsL(RArray<TTzRuleDefinition*>& aTzRuleDefinitions, RArray<TTzRuleUse*>& aTzRuleUses, TInt aStartYear, TInt aEndYear) const
+	{	
+	TInt ruleUseCount = iPersistedEntity.iNumberOfRuleUses;
+	TTzRuleUse* truleUse(NULL);
+	TTzRuleDefinition* truleDef(NULL);	
+	for (TInt i = 0; i < ruleUseCount; i++)
+		{
+		truleUse = const_cast<TTzRuleUse*>(&iReadOnlyTzDb.GetTRuleUse(iPersistedEntity.iOffsetsToRuleUses[i]));
+		
+		// intersect rule use with (startYear,endYear) period
+		if ( (truleUse->iFromYear <= aEndYear) && (truleUse->iUntilYear >= aStartYear) )
+			{
+			// Found one rule use valid during the years of interest - fetch rule definition.
+			// For every year, check if it occurs within (aStartTime,aEndTime)
+			truleDef = const_cast<TTzRuleDefinition*>(&iReadOnlyTzDb.GetTRuleDefinition(truleUse->iOffsetToRuleDefinition));
+			// check that the rule definition has valid data. leave if the data is not valid, as it would mean that the database is corrupt
+			User::LeaveIfError(CTzHelpers::Validate((const TTzRuleDefinition&)*truleDef));
+			
+			// Add rule definition ptr to array
+			aTzRuleDefinitions.Append(truleDef);
+			// Add rule use ptr to array
+			aTzRuleUses.Append(truleUse);
+			}
+		}
+	}
+
+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
+	{
+	TInt startYear = aStartDateTime.Year();
+	TInt endYear = (aActualisedRules.EndYear() < (TUint)aEndDateTime.Year()) ? aActualisedRules.EndYear() : aEndDateTime.Year();	
+	TInt rulesAddedSoFar = 0;
+	TInt yearOfFirstRule = endYear;	
+	TInt count = aTzRuleDefinitions.Count();
+	
+	TInt oldOffset = 0; // Arbitrarily set to zero. Required to create TTzRule.
+	
+	for (TInt i = 0; i < count; i++)
+		{
+		for (TInt year = (startYear > aTzRuleUses[i]->iFromYear) ? startYear : aTzRuleUses[i]->iFromYear ; (year <= endYear) && (year <= aTzRuleUses[i]->iUntilYear); year++)
+			{
+			TTzRule trule(	
+					static_cast<TUint16>(startYear), static_cast<TUint16>(endYear),
+					static_cast<TUint16>(oldOffset), static_cast<TUint16>(aUtcOffset + aTzRuleDefinitions[i]->iStdTimeOffset),static_cast<TMonth>(aTzRuleDefinitions[i]->iMonth), static_cast<TTzRuleDay>(aTzRuleDefinitions[i]->iDayRule),
+					static_cast<TUint8>(aTzRuleDefinitions[i]->iDayOfMonth), static_cast<TUint8>(aTzRuleDefinitions[i]->iDayOfWeek), 
+					static_cast<TTzTimeReference>(aTzRuleDefinitions[i]->iTimeReference), static_cast<TTzTimeReference>(aTzRuleDefinitions[i]->iTimeOfChange));
+			
+			TVTzActualisedRule tActRule = trule.Actualise(year);
+			if ( (tActRule.iTimeOfChange < aEndDateTime) && (tActRule.iTimeOfChange >= aStartDateTime) )
+				{
+				aActualisedRules.AddRuleL(tActRule);
+				// record the year of the first rule added
+				if (rulesAddedSoFar == 0)
+					{
+					yearOfFirstRule = year;
+					}
+				rulesAddedSoFar++;			
+				}
+			}
+		}
+		
+	// In some cases we need to add a "default rule" to aRules. ("Default rule" 
+	// means a rule with zero as DST offset and the start-time of the time-alignment 
+	// as time-of-change). This default rule will be added if no rule exists for the
+	// first year of the time alignment.
+	if ( (rulesAddedSoFar == 0) || (yearOfFirstRule > startYear) )
+		{
+		aActualisedRules.AddRuleL(aDefaultRule);
+		}			
+	}
+	
+//============================================================================================
+
+TInt CTzHelpers::Validate(const TTzRuleDefinition& aRuleDefinition)
+	{
+	if (aRuleDefinition.iStdTimeOffset > KMaxDstOffset)
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iMonth > EDecember)
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iDayRule > KValidatedLastDayRule) // last element of enum TTzRuleDay
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iDayOfMonth > KMaxDayOfMonth)
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iDayOfWeek > ESunday)
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iTimeReference > KValidatedLastTimeReference) // last element of enum TTzTimeReference
+		{
+		return KErrCorrupt;
+		}
+
+	if (aRuleDefinition.iTimeOfChange >= KMinutesInOneDay)
+		{
+		return KErrCorrupt;
+		}
+
+	return KErrNone;
+	}