diff -r 000000000000 -r 2e3d3ce01487 tzservices/tzserver/Client/Source/timezoneconverter.cpp --- /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 +#include "tzrules.h" +#include +#include +#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( + 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; + }