diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/shared/src/agmcalendartime.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendar/shared/src/agmcalendartime.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,720 @@ +// Copyright (c) 2005-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 "agmdate.h" +#include "agmtlsproxy.h" +#include "agmpanic.h" + +#include +#include +#include + +const TInt16 KOffsetUnspecified = KMaxTInt16; +const TUint16 KTzIdFloating = 0x8000; +const TUint16 KTzIdUnspecified = 0x7fff; + +const TUint32 KAgnNewCalTimeMask = (1 << 30); +const TUint32 KAgmTimeFloatingFlag = 0x01; + +// TAgnCalendarTime // + +EXPORT_C TAgnCalendarTime::TAgnCalendarTime() : + iTime(Time::NullTTime()), + iLocalOffsetInMinutes(KOffsetUnspecified), + iTzId(KTzIdUnspecified), + iTimeZoneAccessor(NULL) + { + } + +EXPORT_C void TAgnCalendarTime::SetFloatingL(const TTime& aTime) + { + SetDateTimeL(aTime, ETrue, MAgnCalendarTimeMode::ELocal); + } + +EXPORT_C void TAgnCalendarTime::SetLocalL(const TTime& aTime) + { + SetDateTimeL(aTime, EFalse, MAgnCalendarTimeMode::ELocal); + } + +EXPORT_C void TAgnCalendarTime::SetUtcL(const TTime& aTime) + { + SetDateTimeL(aTime, EFalse, MAgnCalendarTimeMode::EUtc); + } + +void TAgnCalendarTime::SetNull() + { + iTime = Time::NullTTime(); + iLocalOffsetInMinutes = KOffsetUnspecified; + } + +EXPORT_C TTime TAgnCalendarTime::LocalL() const + { + if (TimeMode() == MAgnCalendarTimeMode::EFixedTimeZone) + { + return DateTimeL(MAgnCalendarTimeMode::EFixedLocal); + } + return DateTimeL(MAgnCalendarTimeMode::ELocal); + } + +EXPORT_C TTime TAgnCalendarTime::UtcL() const + { + return DateTimeL(MAgnCalendarTimeMode::EUtc); + } + +void TAgnCalendarTime::SetDateTimeL(const TTime& aTime, TBool aFloating, MAgnCalendarTimeMode::TFormat aFormat) +/** Set the time and time mode of the AgnCalendarTime +@internalAll + +@param aTime The time to be stored, can be UTC if aFormat is EUtc, or local if aFormat is ELocal or EFixedLocal +@param aMode Reference to a MAgnCalendarTimeMode derived time mode class. This time mode must be retrieved from AgnDateTime or CAgnTlsProxy +@param aFormat The time format of aTime +*/ + { + if (!AgnDateTime::IsValidAgendaTTime(aTime)) + { + // If the time is outside the range between MinDate and MaxDate, don't + // convert it, but normalise it to the max or min datetimes as + // appropriate. + if(aTime == Time::NullTTime()) + { + iTime = aTime; + } + else if(aTime <= AgnDateTime::MinDate()) + { + iTime = AgnDateTime::MinDate(); + } + else if(aTime >= AgnDateTime::MaxDate()) + { + iTime = AgnDateTime::MaxDate(); + } + iLocalOffsetInMinutes = KOffsetUnspecified; + } + else + { + if ( ! aFloating) + { + if (aFormat == MAgnCalendarTimeMode::EUtc) + { + // If the time is UTC, just store it. The offset is unknown at this point. + iTime = aTime; + iLocalOffsetInMinutes = KOffsetUnspecified; + } + else + { + // If the time is local, convert it and store the offset as well as the time. + TTime localTime(aTime); + TTime utcTime(aTime); + TimeZoneAccessor()->FixedTimeMode().ToL(aFormat, utcTime); + //In order to ensure UTC time is still within the range of Max and Min time + //after the conversion. Any UTC time that is not within the range is converted + //to Max or Min time. + if (utcTime <= AgnDateTime::MinDate()) + { + localTime = utcTime = AgnDateTime::MinDate(); + } + else if (utcTime >= AgnDateTime::MaxDate()) + { + localTime = utcTime = AgnDateTime::MaxDate(); + } + iTime = utcTime; + StoreNewOffset(localTime); + SetTzId(TimeZoneAccessor()->CurrentTzId()); + } + SetFloatingFlag(EFalse); + } + else + { + // floating time + if (aFormat == MAgnCalendarTimeMode::EUtc) + { + TTime utcTime(aTime); + TTime localTime(aTime); + TimeZoneAccessor()->FloatingTimeMode().ToL(aFormat, localTime); + iTime = localTime; + StoreNewOffset(utcTime); + SetTzId(TimeZoneAccessor()->CurrentTzId()); + } + else + { + iTime = aTime; + iLocalOffsetInMinutes = KOffsetUnspecified; + } + SetFloatingFlag(ETrue); + } + } + __ASSERT_DEBUG(IsValidTime(), User::Invariant()); + } + +EXPORT_C TTime TAgnCalendarTime::DateTimeL(MAgnCalendarTimeMode::TFormat aFormat) const + { + if(iTime <= AgnDateTime::MinDate() || iTime >= AgnDateTime::MaxDate() || iTime == Time::NullTTime()) + { + // If the time is outside the range between MinDate and MaxDate, don't convert it. + // If the time is to be returned in UTC, don't convert it. + return iTime; + } + + if ((TimeMode() == MAgnCalendarTimeMode::EFixedUtc && aFormat == MAgnCalendarTimeMode::EUtc) || + (TimeMode() == MAgnCalendarTimeMode::EFloating && aFormat == MAgnCalendarTimeMode::ELocal) || + (TimeMode() == MAgnCalendarTimeMode::EFloating && aFormat == MAgnCalendarTimeMode::EFixedLocal) || + (TimeMode() == MAgnCalendarTimeMode::EFixedTimeZone && aFormat == MAgnCalendarTimeMode::EFixedLocal)) + { + return iTime; + } + + // In this case the time is to be converted + TUint16 tzId = TimeZoneAccessor()->CurrentTzId(); // Check whether or not the time zone has changed. + + // Note that each TAgnCalendarTime's offset is updated on demand, so there is no need to update all + // offsets when the local time zone changes. + + if (TimeMode() == MAgnCalendarTimeMode::EFixedUtc) + { + if (iLocalOffsetInMinutes == KOffsetUnspecified || + TzId() != tzId) + { + // If the offset is unknown or the time zone has changed, recalculate the offset. + TTime newLocalTime(iTime); + CalendarTimeMode()->FromL(aFormat, newLocalTime); + StoreNewOffset(newLocalTime); + SetTzId(tzId); + } + } + else if (TimeMode() == MAgnCalendarTimeMode::EFloating) + { + if (iLocalOffsetInMinutes == KOffsetUnspecified || + TzId() != tzId) + { + // If the offset is unknown or the time zone has changed, recalculate the offset. + TTime newUtcTime(iTime); + CalendarTimeMode()->FromL(aFormat, newUtcTime); + StoreNewOffset(newUtcTime); + SetTzId(tzId); + } + } + else // using rule time mode + { + User::Leave(KErrNotSupported); + } + + return iTime + TTimeIntervalMinutes(iLocalOffsetInMinutes); + } + + +void TAgnCalendarTime::StoreNewOffset(const TTime& aTime) const + { + TTimeIntervalMinutes mins; + aTime.MinutesFrom(iTime, mins); + iLocalOffsetInMinutes = mins.Int(); + } + +CAgnTlsProxy* TAgnCalendarTime::TimeZoneAccessor() const + { + if (!iTimeZoneAccessor) + { + iTimeZoneAccessor = static_cast(Dll::Tls()); + __ASSERT_ALWAYS(iTimeZoneAccessor, User::Invariant()); + } + return iTimeZoneAccessor; + } + +EXPORT_C TBool TAgnCalendarTime::IsSet() const + { + return (iTime != Time::NullTTime()); + } + + + +EXPORT_C TBool TAgnCalendarTime::operator==(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime == aTime.iTime); + } + else + { + return (UtcL() == aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::operator!=(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime != aTime.iTime); + } + else + { + return (UtcL() != aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::operator<(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime < aTime.iTime); + } + else + { + return (UtcL() < aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::operator>(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime > aTime.iTime); + } + else + { + return (UtcL() > aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::operator<=(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime <= aTime.iTime); + } + else + { + return (UtcL() <= aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::operator>=(const TAgnCalendarTime& aTime) const + { + if (TimeMode() == aTime.TimeMode() && + (TimeMode() == MAgnCalendarTimeMode::EFixedUtc || TimeMode() == MAgnCalendarTimeMode::EFloating)) + { + // both times are either floating or fixed, no conversion needed + return (iTime >= aTime.iTime); + } + else + { + return (UtcL() >= aTime.UtcL()); + } + } + + + +EXPORT_C TBool TAgnCalendarTime::IsValidTime() const + { + TBool isNullTime(iTime == Time::NullTTime()); + TBool isWithinValidRange(iTime >= Time::MinTTime() && iTime <= Time::MaxTTime()); + return (isNullTime || isWithinValidRange); + } + +/* +In v9.1 time was stored as a TUint64 value of number of microseconds since midnight +January 1st, 0 AD nominal Gregorian. + +The TAgnCalendarTime count time is a valid if it lay between Midnight, January 1st 1900 and +Midnight, December 31st 2100. It means TUint64 value should be between 0x00D504A2C672E000 and 0x00eb8d745a6fc000. +Also NullTime (0x8000000000000000) is supported. + +Internalize: +1) read low 32 bits +2) read high 32 bits +3) if 2nd msb bit of high = 1 then: (note the 2nd msb bit is used because the 1st msb bit is used by Time::NullTTime(). + - must be reading v9.2+ format (iTime values that are either agn null time or between agn min time to agn max time can never have this msb bit set to 1) + - flip 2nd msb bit to 0 to create iTime later in step 4 + - read another 32 bits and if lsb = 1 set to floating mode else must be fixed mode (other 31 bits will be used for TzId in future) + - read yet another 32 bits (future padding) +4) set iTime = TTime(MAKE_TINT64(high, low)) + + +Externalize: +1) write low 32 bits of iTime, +2) mask the high 32 bits of iTime with (1<<30) to signify a v9.2+ time format +3) write masked high bits of iTime +4) write another 32 bits (lsb = 0 for fixed time mode, 1 for floating time mode) +5) write yet another 32 bits (value = 0 always for future use) +*/ +EXPORT_C void TAgnCalendarTime::InternalizeL(RReadStream& aStream) + { + TUint32 low = aStream.ReadUint32L(); + TUint32 high = aStream.ReadUint32L(); + + if (high & KAgnNewCalTimeMask) + { + // reading v9.2+ format + high = high & ~KAgnNewCalTimeMask; + + TUint32 attr = aStream.ReadUint32L(); //read attribute + if (attr & KAgmTimeFloatingFlag) + { + SetFloatingFlag(ETrue); + } + else + { + SetFloatingFlag(EFalse); + } + + aStream.ReadUint32L(); //reserved 32 bits for future use + } + else + { + // for backcompatibility, v9.1 only support fix time mode + iTzId = KTzIdUnspecified; + SetFloatingFlag(EFalse); + } + + iTime = TTime(MAKE_TINT64(high, low)); //old data format + __ASSERT_ALWAYS(IsValidTime(), User::Leave(KErrCorrupt)); + } + +void TAgnCalendarTime::ExternalizeL(RWriteStream& aStream) const + { + aStream << I64LOW(iTime.Int64()); + aStream << (I64HIGH(iTime.Int64()) | KAgnNewCalTimeMask); + TUint32 attr(0); + if (TimeMode() == MAgnCalendarTimeMode::EFloating) + { + attr |= KAgmTimeFloatingFlag; + } + + aStream << attr; + aStream.WriteUint32L(0); // reserved 32 bits for future use + + } + +void TAgnCalendarTime::SetFloatingFlag(TBool aFloating) const + { + if (aFloating) + { + iTzId |= KTzIdFloating; + } + else + { + iTzId &= ~KTzIdFloating; + } + } + +void TAgnCalendarTime::SetTzId(TUint16 aTzId) const + { + iTzId = aTzId | (iTzId & KTzIdFloating); + } + +TUint16 TAgnCalendarTime::TzId() const + { + return (iTzId & ~KTzIdFloating); + } + +const MAgnCalendarTimeMode* TAgnCalendarTime::CalendarTimeMode() const + { + if (iTzId & KTzIdFloating) + { + return &TimeZoneAccessor()->FloatingTimeMode(); + } + else + { + // this is needed for alarm info reconsturction + return &TimeZoneAccessor()->FixedTimeMode(); + } + } + +EXPORT_C MAgnCalendarTimeMode::TTimeMode TAgnCalendarTime::TimeMode() const + { + if (CalendarTimeMode()) + { + return CalendarTimeMode()->TimeMode(); + } + return MAgnCalendarTimeMode::EFixedUtc; // default is fixed time mode if not set + } + +/*static*/ TInt TAgnCalendarTime::Compare(const TAgnCalendarTime& aLeft, const TAgnCalendarTime& aRight) + { + if (aLeft == aRight) + { + return 0; + } + else if (aLeft > aRight) + { + return 1; + } + return -1; + } + +/*static*/ void TAgnCalendarTime::InsertInOrderL(RArray& aTimeArray, const TAgnCalendarTime& aTimeToInsert) + { + TLinearOrder agnCalTimeOrder(TAgnCalendarTime::Compare); + TInt err = aTimeArray.InsertInOrder(aTimeToInsert, agnCalTimeOrder); + if (err != KErrAlreadyExists) + { + User::LeaveIfError(err); + } + } + +/*static*/ TBool TAgnCalendarTime::CompareTimeArrays(const RArray* aLeft, const RArray* aRight) + { + if (aLeft == NULL) + { + if (aRight == NULL) + { + return ETrue; + } + return EFalse; + } + + // aLeft is non-NULL + if (aRight == NULL) + { + return EFalse; + } + + if (aLeft->Count() != aRight->Count()) + { + return EFalse; + } + + const TInt KTimeCount = aLeft->Count(); + for (TInt i = 0; i < KTimeCount; ++i) + { + if ((*aLeft)[i] != (*aRight)[i]) + { + return EFalse; + } + } + return ETrue; + } + +/*static*/ void TAgnCalendarTime::InternalizeTimeArrayL(RArray& aArray, RReadStream& aStream) + { + aArray.Reset(); + const TInt KCount = aStream.ReadUint16L(); + + TAgnCalendarTime time; + for (TInt i = 0; i < KCount; ++i) + { + aStream >> time; + aArray.AppendL(time); + } + } + +/*static*/ void TAgnCalendarTime::ExternalizeTimeArrayL(RArray& aArray, RWriteStream& aStream) + { + const TInt KCount = aArray.Count(); + aStream.WriteUint16L(KCount); + + for (TInt i = 0; i < KCount; ++i) + { + aStream << aArray[i]; + } + } + +// TAgnCalendarFixedTimeMode // + +TAgnCalendarFixedTimeMode::TAgnCalendarFixedTimeMode(CTzConverter& aTimeConverter) : + iTimeConverter(aTimeConverter) + { + } + +void TAgnCalendarFixedTimeMode::ToL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case ELocal: + case EFixedLocal: + { + User::LeaveIfError(iTimeConverter.ConvertToUniversalTime(aTime)); + } + case EUtc: + { + // do nothing - no conversion necessary + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + }; + } + +void TAgnCalendarFixedTimeMode::FromL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case ELocal: + case EFixedLocal: + { + User::LeaveIfError(iTimeConverter.ConvertToLocalTime(aTime)); + break; + } + case EUtc: + { + // do nothing - no conversion necessary + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + } + } + +MAgnCalendarTimeMode::TTimeMode TAgnCalendarFixedTimeMode::TimeMode() const + { + return MAgnCalendarTimeMode::EFixedUtc; + } + +// TAgnCalendarFixedUsingRulesTimeMode // + +TAgnCalendarFixedUsingRulesTimeMode::TAgnCalendarFixedUsingRulesTimeMode(CTzRules& aTimeZoneRules, CTzConverter& aTimeConverter) : + iTimeZoneRules(aTimeZoneRules), iTimeConverter(aTimeConverter) + { + } + +const CTzRules& TAgnCalendarFixedUsingRulesTimeMode::TzZone() const + { + return iTimeZoneRules; + } + +void TAgnCalendarFixedUsingRulesTimeMode::ToL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case ELocal: + { + User::LeaveIfError(iTimeConverter.ConvertToLocalTime(aTime)); + break; + } + case EUtc: + { + iTimeZoneRules.ConvertToLocalL(aTime); + break; + } + case EFixedLocal: + { + // do nothing - no conversion necessary + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + }; + } + +void TAgnCalendarFixedUsingRulesTimeMode::FromL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case EUtc: + { + iTimeZoneRules.ConvertToUtcL(aTime); + break; + } + case ELocal: + { + User::LeaveIfError(iTimeConverter.ConvertToUniversalTime(aTime)); + break; + } + case EFixedLocal: + { + // do nothing - no conversion necessary + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + } + } + +MAgnCalendarTimeMode::TTimeMode TAgnCalendarFixedUsingRulesTimeMode::TimeMode() const + { + return MAgnCalendarTimeMode::EFixedTimeZone; + } + +// TAgnCalendarFloatingTimeMode // + +TAgnCalendarFloatingTimeMode::TAgnCalendarFloatingTimeMode(CTzConverter& aTimeConverter) : + iTimeConverter(aTimeConverter) + { + } + +void TAgnCalendarFloatingTimeMode::ToL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case ELocal: + case EFixedLocal: + { + // do nothing - no conversion necessary + break; + } + case EUtc: + { + User::LeaveIfError(iTimeConverter.ConvertToLocalTime(aTime)); + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + }; + } + +void TAgnCalendarFloatingTimeMode::FromL(MAgnCalendarTimeMode::TFormat aFormat, TTime& aTime) const + { + switch (aFormat) + { + case ELocal: + case EFixedLocal: + { + // do nothing - no conversion necessary + break; + } + case EUtc: + { + User::LeaveIfError(iTimeConverter.ConvertToUniversalTime(aTime)); + break; + } + default: + { + Panic(EAgmErrUnsupportedTimeMode); + } + }; + } + +MAgnCalendarTimeMode::TTimeMode TAgnCalendarFloatingTimeMode::TimeMode() const + { + return MAgnCalendarTimeMode::EFloating; + }