tzservices/tzserver/Client/Source/timezoneconverter.cpp
changeset 0 2e3d3ce01487
child 81 676b6116ca93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tzservices/tzserver/Client/Source/timezoneconverter.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,365 @@
+// Copyright (c) 1997-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 <tz.h>
+#include "tzrules.h"
+#include <vtzrules.h>
+#include <tzconverter.h>
+#include "tzruleholder.h"
+#include "tzchangenotifier.h"
+
+//
+// CTzRuleHolder
+//
+
+CTzRuleHolder::CTzRuleHolder( RTz& aTzServer ) :
+    iTzServer (aTzServer)
+	{
+	}
+
+CTzRuleHolder::~CTzRuleHolder()
+	{
+	delete iTzChangeNotifier;
+	delete iTzActualisedRules;
+	delete iTzRules;
+	}
+
+CTzRuleHolder* CTzRuleHolder::NewL( RTz& aTzServer )
+	{
+	CTzRuleHolder* self = new(ELeave) CTzRuleHolder( aTzServer );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+    }
+
+void CTzRuleHolder::ConstructL()
+    {
+	// Must be connected.
+	if (!iTzServer.Handle())
+	    {
+	    User::Leave( KErrNotReady );
+	    }
+
+	CTzId* tzId = iTzServer.GetTimeZoneIdL();
+	SetCurrentTzId(tzId->TimeZoneNumericID());
+	delete tzId;
+	
+    iTzChangeNotifier = CTzChangeNotifier::NewL( *this );
+    iTzChangeNotifier->StartObserving();
+    }
+
+/**
+Clears the cache.
+*/
+void CTzRuleHolder::ClearRules()
+	{
+	delete iTzActualisedRules;
+	iTzActualisedRules = NULL;
+	delete iTzRules;
+	iTzRules = NULL;
+	iCurrentTzId = 0;
+	}
+
+
+
+
+void CTzRuleHolder::DoConvertL(TTime& aTime, TTzTimeReference aTimerRef)
+	{
+	// The change notifier may not have had a chance to run yet
+	// so check if it is ready to run now to force the update of the client side cache
+	iTzChangeNotifier->RunIfReadyL();
+	
+	if (!(iTzRules && iTzRules->RulesApply(aTime) ) )
+		{
+		if (!iTzRules)
+
+			{
+			TTime startTime(TDateTime(0,EJanuary,0,0,0,0,0));
+			TTime endTime(TDateTime(KMaxYear,EDecember,30,23,59,59,0));
+			iTzRules = iTzServer.GetTimeZoneRulesL(startTime, endTime, aTimerRef);
+			}
+		}
+		
+	// adjust for aTimerRef?
+	TDateTime dateTime = aTime.DateTime();
+	TUint year = dateTime.Year();
+	if (!(iTzActualisedRules 
+			&& year >= iTzActualisedRules->StartYear() 
+			&& year <= iTzActualisedRules->EndYear() ) )
+		{
+		// avoid over/under flow
+		TUint startYear = year;
+		TUint endYear = startYear;
+		if (startYear >= (KRuleCacheLowerLimit+1))
+			{
+			startYear -= (KRuleCacheLowerLimit+1);
+			}
+		if (endYear < (KMaxTUint - KRuleCacheUpperLimit))
+			{
+			endYear += KRuleCacheUpperLimit;
+			}
+
+		CVTzActualisedRules* newRules = CVTzActualisedRules::NewL(startYear, endYear);
+		CleanupStack::PushL(newRules);
+		iTzRules->GetActualisedRulesL(*newRules);
+		CleanupStack::Pop(newRules);
+
+		delete iTzActualisedRules;
+		iTzActualisedRules = newRules;
+		}
+		
+	User::LeaveIfError(iTzRules->ConvertTime(*iTzActualisedRules, aTime, aTimerRef));
+	}
+
+/**
+Handles notifications from the Time Zone Server
+if the Time Zone Database Changes or the System Time Zone is Changed then
+the cached rules are no longer valid. Discard them.
+*/
+void CTzRuleHolder::NotifyTimeZoneChangeL(RTz::TTzChanges aChange)
+	{
+	User::LeaveIfError(aChange);
+
+	if (aChange == RTz::ETZDatabaseChanged ||
+		aChange == RTz::ETZSystemTimeZoneChanged)
+		{
+		ClearRules();
+		CTzId* tzId = iTzServer.GetTimeZoneIdL();
+		SetCurrentTzId(tzId->TimeZoneNumericID());
+		delete tzId;
+		}
+		
+	// re-request notification
+	iTzChangeNotifier->StartObserving();
+
+	}
+	
+//
+// CTzChangeNotifier
+//
+CTzChangeNotifier::~CTzChangeNotifier()
+	{
+	Cancel();
+	}
+
+CTzChangeNotifier* CTzChangeNotifier::NewL( CTzRuleHolder& aRulesHolder )
+
+	{
+	CTzChangeNotifier* self = new(ELeave) CTzChangeNotifier( aRulesHolder );
+	CActiveScheduler::Add(self);
+	return self;
+	}
+
+/**
+Starts observing for changes to the time zone from the the Time Zone Server.
+@return KErrNotReady if already active, KErrNotReady if session not
+open, otherwise KErrNone.
+*/
+TInt CTzChangeNotifier::StartObserving()
+	{
+	if (IsActive())
+		{
+		return KErrNotReady;
+		}
+
+	iStatus = KRequestPending;
+	SetActive();
+	iRulesHolder.Server().RegisterTzChangeNotifier(iStatus);
+	return KErrNone;
+	}
+
+/**
+Stops Observing the Time Zone Server.
+*/
+void CTzChangeNotifier::StopObserving()
+	{
+	Cancel();
+	}
+
+void CTzChangeNotifier::RunIfReadyL()
+	{
+	if (IsActive() && iStatus != KRequestPending)
+		{
+		RunL();
+		Cancel();
+		StartObserving();
+		}
+	}
+
+void CTzChangeNotifier::RunL()
+	{
+	iRulesHolder.NotifyTimeZoneChangeL( static_cast<RTz::TTzChanges>(
+	    iStatus.Int()) );
+	}
+
+void CTzChangeNotifier::DoCancel()
+	{
+	iRulesHolder.Server().CancelRequestForNotice();
+	}
+
+//
+// CTzConverter
+//
+const RTz& CTzConverter::Server() const
+	{
+	return iTzServer;
+	}
+
+CTzConverter::CTzConverter(RTz& aTzServer) : iTzServer(aTzServer)
+	{
+	}
+
+void CTzConverter::ConstructL()
+	{
+	// Caching is now done through RTz so enable its caching. This will
+	// do nothing if connected, but if unconnected, then this will leave 
+	// with KErrNotReady.
+	iTzServer.StartCachingL();
+
+	}
+
+// Handles notifications from the Time Zone Server
+// if the Time Zone Database Changes or the System Time Zone is Changed then
+// the cached rules is no longer valid. discard it.
+void CTzConverter::NotifyTimeZoneChangeL(RTz::TTzChanges /*aChange*/)
+	{
+	// No longer does anything. This is done in RTz.
+	}
+
+/** 
+CTzConverter factory method.
+
+Provides client side caching for conversions in the local time zone. Caching 
+is done through RTz but enabled through this interface. When caching has been 
+enabled by this class and the RTz functions for local time zone conversion are
+used, they too will use the cache instead of the server. Multiple CTzConverter's
+can use the same RTz session. Each converter will be notified by the server if
+the time zone changes, and the cache will be updated appropriately.
+
+
+To disable caching in RTz, the session must be closed. Caching will be 
+re-enabled if a CTzConverter associated with the RTz is later used again 
+for local time zone conversions.
+ 
+This will leave with KErrNotReady if the RTz passed in is not connected.
+
+@param aTzServer Connection to the time zone server. 
+@return A pointer to the new CTzConverter object. The caller takes ownership.
+*/
+EXPORT_C CTzConverter* CTzConverter::NewL(RTz& aTzServer)
+	{
+	CTzConverter* self = new(ELeave) CTzConverter(aTzServer);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CTzConverter::~CTzConverter()
+	{
+	}
+
+
+
+
+/** 
+Converts a time from UTC to local (wall-clock) time 
+for the current system time zone.
+@param aTime On entry, contains the UTC time to be converted 
+and the converted value on exit. 
+@return KErrNone if successful, otherwise another system error code.
+*/
+EXPORT_C TInt CTzConverter::ConvertToLocalTime(TTime& aTime)
+	{
+
+
+	// Ensure that caching is enabled. It will be disabled if the TZ server
+	// has become disconnected since this object was created.
+	TRAPD( error, iTzServer.StartCachingL() );
+	if (error == KErrNone)
+	    {
+	    return iTzServer.ConvertToLocalTime( aTime );
+	    }
+	else
+	    {
+	    return error;
+	    }
+	}
+
+/** 
+Converts a time from UTC to the local (wall-clock) time 
+for the specified time zone.
+
+@param aTime On entry, contains the UTC time to be converted, 
+and the converted value on exit.
+@param aZone Time zone ID.
+@return KErrNone if successful, otherwise another system error code.
+*/
+EXPORT_C TInt CTzConverter::ConvertToLocalTime(TTime& aTime,
+													 const CTzId& aZone)
+	{
+	return (iTzServer.ConvertToLocalTime(aTime, aZone));
+	}
+
+/** 
+Converts a local (wall-clock) time for the current system time zone into UTC.
+@param aTime On entry, contains the local time to be converted, 
+and the converted value on exit.
+@return KErrNone if successful, otherwise another system error code.
+*/
+EXPORT_C TInt CTzConverter::ConvertToUniversalTime(TTime& aTime)
+	{
+
+
+	// Ensure that caching is enabled. It will be disabled if the TZ server
+	// has become disconnected since this object was created.
+	TRAPD( error, iTzServer.StartCachingL() );
+	if (error == KErrNone)
+	    {
+    	return iTzServer.ConvertToUniversalTime( aTime );
+    	}
+    else
+        {
+        return error;
+        }
+	}
+
+/** 
+Converts a local (wall-clock) time for the specified time zone into UTC.
+@param aTime On entry, contains the local time to be converted, 
+and the converted value on exit. 
+@param aZone The time zone ID.
+@return KErrNone if successful, otherwise another system error code.
+*/
+EXPORT_C TInt CTzConverter::ConvertToUniversalTime(TTime& aTime,
+													const CTzId& aZone)
+	{
+
+	return (iTzServer.ConvertToUniversalTime(aTime, aZone));
+	}
+
+/** 
+Get the numerical ID of the current time zone.
+@return The time zone ID.
+*/
+EXPORT_C TUint16 CTzConverter::CurrentTzId()
+	{
+	TUint16 tzId = iTzServer.CurrentCachedTzId();
+	return tzId;
+	}