--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappsupport/chinesecalendaralg/pluginsrc/chinesecalendar.cpp Fri Mar 12 15:42:35 2010 +0200
@@ -0,0 +1,368 @@
+// Copyright (c) 2000-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:
+// Implementation of the TChineseCalendar class.
+//
+
+#include "chinesecalendar.h"
+#include "arithmeticaldate.h"
+#include "gregoriancalendar.h"
+
+#if defined(_DEBUG)
+_LIT(KCalconPanic,"Calcon");
+#endif
+
+const TUint KMonthInvalid=0;
+const TUint K29DayMonth=1;
+const TUint K30DayMonth=2;
+const TUint K29DayLeapMonth=3;
+const TUint K30DayLeapMonth=4;
+
+const TUint KMonthMask=1<<15;
+const TUint KLeapMonthShift=28;
+
+const TInt KNoOfYearsInCycle = 60;
+
+enum TCalconPanic
+ {
+ ECalconChineseFromFixedMonthInvalid=0,
+ ECalconChineseToFixedLeapYearInvalid,
+ ECalconGetDataYearOutOfRange,
+ ECalconGetDataMonthOutOfRange,
+ ECalconGetNewYearYearOutOfRange
+ };
+
+TUint TCalconData::GetData(TInt aCycle, TInt aYear, TInt aMonth) const
+ {
+ __ASSERT_DEBUG((aYear>=0 && aYear<=59), User::Panic(_L("Calcon"), ECalconGetDataYearOutOfRange)); //year range is 0..59
+ __ASSERT_DEBUG((aMonth>=0 && aMonth<=12), User::Panic(_L("Calcon"), ECalconGetDataMonthOutOfRange));//month range is 0..12
+
+ TInt y=(aCycle*KNoOfYearsInCycle)+aYear;
+ y-=(KFirstYear-1); //there are KFirstYear-1 entries missing from the head of the table
+ TUint16 x=iCalConDataMonth[y];
+
+ TUint mask=KMonthMask>>aMonth;
+
+ TInt flag=K29DayMonth;
+ if (x & mask)
+ flag=K30DayMonth;
+
+ TUint leapMonth=iCalConDataYear[y]>>KLeapMonthShift;
+ leapMonth--;
+
+ if ((TUint)aMonth==leapMonth)
+ flag+=2; //--> K29/30DayLeapMonth
+
+ if ((aMonth==12) && (leapMonth==0))
+ flag=KMonthInvalid;//month doesn't exist
+
+ return flag;
+ }
+
+TUint TCalconData::GetNewYear(TInt aCycle, TInt aYear) const
+ {
+ __ASSERT_DEBUG((aYear>=0 && aYear<=59), User::Panic(_L("Calcon"), ECalconGetNewYearYearOutOfRange));
+ TInt y=(aCycle*KNoOfYearsInCycle)+aYear;
+ y-=(KFirstYear-1);
+ return (iCalConDataYear[y] & 0x0fffffff);
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: ChineseToDateTime
+// Arguments: TDateTime &
+//
+// Comments: This function converts the date held within
+// the TChineseCalendar class to a TDateTime format and
+// places it in the TDateTime class provided.
+//
+// Return: void
+//------------------------------------------------------
+void TChineseCalendar::ChineseToDateTime(TDateTime &aDT)
+ {
+ TArithmeticalDate gregDate;
+ TGregorianCalendar greg(iJulianDay);
+
+ greg.GregFromJulianDay(gregDate,iJulianDay);
+ aDT.Set(0,EJanuary,0,0,0,0,0);
+
+ aDT.SetDay(gregDate.iDay - KCalConvMonthOffsetByOne);
+ aDT.SetMonth((TMonth)(gregDate.iMonth - KCalConvMonthOffsetByOne));
+ aDT.SetYear(gregDate.iYear);
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: DateTimeToChinese
+// Arguments: TDateTime &
+//
+// Comments: Sets the date held in the given TDateTime
+// class to the TChineseCalendar class
+//
+// Return: void
+//------------------------------------------------------
+void TChineseCalendar::DateTimeToChinese(const TDateTime &aDT)
+ {
+ TArithmeticalDate gregDate;
+ TGregorianCalendar greg;
+
+ gregDate.iDay = aDT.Day() + KCalConvMonthOffsetByOne;
+ gregDate.iMonth = (TInt)aDT.Month() + KCalConvMonthOffsetByOne;
+ gregDate.iYear = aDT.Year();
+
+ iJulianDay = greg.GregToJulianDay(gregDate);
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: SetDate
+// Arguments: TChineseDate&
+//
+// Comments: this function sets the julian day value
+// in the base class from the given
+// TChineseDate
+//
+// Return: None
+//------------------------------------------------------
+TInt TChineseCalendar::SetDate(const TChineseDate &aDate)
+ {
+ TReal jD;
+ TChineseDate ChinDate = aDate;
+
+ if(!ValidDate(ChinDate))
+ return KErrArgument;
+
+ if (!ChineseToFixed(aDate,jD))
+ return KErrArgument;
+
+ if (jD<KFirstJulianDate || jD>KLastJulianDate)
+ return KErrArgument;
+
+ iJulianDay = (TInt)jD;
+ return KErrNone;
+ }
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: GetDate
+// Arguments: TChineseDate &
+//
+// Comments: This function Determines the chinese date and
+// places it in the TChineseDate class provided
+// for the julian day value held internally in the
+// Chinese class.
+//
+// Return: None
+//------------------------------------------------------
+TInt TChineseCalendar::GetDate(TChineseDate &aDate)
+ {
+ return ChineseFromFixed(aDate,iJulianDay);
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: ChineseToFixed
+// Arguments: TChineseDate , TReal &
+// TChineseDate members start at 1 (not zero)
+//
+// Comments: This function converts a chinese date to
+// to a julian day value.
+//
+// Return: TBool ETrue if date valid, else EFalse
+//------------------------------------------------------
+TBool TChineseCalendar::ChineseToFixed(const TChineseDate& aDate, TReal &aJulianDay) const
+ {
+ TInt cycle=aDate.iCycle-KFirstCycle; //cycle starts from zero
+ TInt year=aDate.iYear-1; //year is 0..59
+
+ TInt days=0;
+
+ TInt targetMonth=aDate.iMonth; //targetMonth is 1..12
+ TBool leap=aDate.iLeapMonth;
+ if (leap)
+ {
+ targetMonth++;
+ if (iData.GetData(cycle, year, targetMonth-1)<3)
+ return EFalse; //not a leap month
+ }
+
+ TInt month=1;
+ while (month<=targetMonth)
+ {
+ TInt daysFlag=iData.GetData(cycle, year, month-1);
+
+//We need to handle case where targetMonth is a leap month
+//Eg if Chinese month==6 targetMonth will be 6
+//Eg but if Chinese month 5 is a leap month, month 6 will be 5(leap) so we need to take it into account
+//BUT Eg if Chinese momth== 7(leap) we've already taken this into account.
+ if (month==targetMonth)
+ if ((leap) || (daysFlag<3))
+ break;
+
+ switch (daysFlag)
+ {
+ case KMonthInvalid:
+ return EFalse;
+ case K29DayMonth:
+ days+=29;
+ break;
+ case K30DayMonth:
+ days+=30;
+ break;
+ case K29DayLeapMonth:
+ __ASSERT_DEBUG(!leap, User::Panic(KCalconPanic,ECalconChineseToFixedLeapYearInvalid));
+ leap=ETrue;
+ targetMonth++;
+ days+=29;
+ break;
+ case K30DayLeapMonth:
+ __ASSERT_DEBUG(!leap, User::Panic(KCalconPanic,ECalconChineseToFixedLeapYearInvalid));
+ leap=ETrue;
+ targetMonth++;
+ days+=30;
+ break;
+ }
+ month++;
+ }
+
+//Check that if days==30, the requested month actually has 30 days
+ TInt checkMonth = aDate.iMonth;
+ if (leap)
+ checkMonth++; //this is the month requested by the user
+ TUint daysFlag=iData.GetData(cycle, year, checkMonth-1);
+
+ if ((aDate.iDay==30) && ((daysFlag==K29DayMonth) || (daysFlag==K29DayLeapMonth)))
+ return EFalse;
+
+ days+=aDate.iDay-1;
+
+ days+=iData.GetNewYear(cycle, year);//add the New Year
+ aJulianDay=days;
+ return ETrue;
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: ChineseFromFixed
+// Arguments: TChineseDate &, TReal
+//
+// Comments: this function converts a julian day value to
+// a chinese date in the form TChineseDate
+//
+// Return: None
+//------------------------------------------------------
+TInt TChineseCalendar::ChineseFromFixed(TChineseDate &aDate, const TReal& aJulianDay) const
+ {
+ if ((aJulianDay<KFirstJulianDate)
+ || (aJulianDay>KLastJulianDate))
+ return KErrArgument;
+
+ TInt cycleIndex=0;
+
+ while ((cycleIndex < KLastCycle-KFirstCycle)
+ && (aJulianDay >= iData.GetNewYear(cycleIndex+1,0)))
+ cycleIndex++;
+
+ aDate.iCycle=cycleIndex + KFirstCycle;
+ TInt chineseNewYear;
+ TInt yearCount=0;
+ if (cycleIndex==0)
+ yearCount=KFirstYear-1;
+
+ while (yearCount<60 && aJulianDay >= iData.GetNewYear(cycleIndex,yearCount))
+ yearCount++;
+
+ aDate.iYear=yearCount;
+ chineseNewYear = iData.GetNewYear(cycleIndex,--yearCount);
+
+ TInt addedNumberOfDays = 0;
+ TInt previousAddedNumberOfDays = 0;
+ TInt monthCount = 1;
+ aDate.iMonth = 0;
+
+ TInt monthNumber; // 0=No month exists, 1 = 29 day month, 2 = 30 day month, 3 = 29 day leap month, 4 = 30 day leap month
+
+ while (aJulianDay >= (chineseNewYear + addedNumberOfDays))
+ {
+ previousAddedNumberOfDays = addedNumberOfDays;
+ monthNumber = iData.GetData(cycleIndex,yearCount,monthCount-1);
+
+ switch (monthNumber)
+ {
+ case KMonthInvalid:
+ __ASSERT_DEBUG(0, User::Panic(_L("Calcon"),ECalconChineseFromFixedMonthInvalid));
+ break;
+ case K29DayMonth:
+ addedNumberOfDays += 29;
+ aDate.iMonth++;
+ aDate.iLeapMonth = EFalse;
+ break;
+ case K30DayMonth:
+ addedNumberOfDays += 30;
+ aDate.iMonth++;
+ aDate.iLeapMonth = EFalse;
+ break;
+ case K29DayLeapMonth:
+ addedNumberOfDays += 29;
+ aDate.iLeapMonth = ETrue;
+ break;
+ case K30DayLeapMonth:
+ addedNumberOfDays += 30;
+ aDate.iLeapMonth = ETrue;
+ break;
+ }
+ monthCount++;
+ }
+
+ aDate.iDay = (TInt)aJulianDay - chineseNewYear-previousAddedNumberOfDays;
+ aDate.iDay++;
+ return KErrNone;
+ }
+
+//------------------------------------------------------
+// Class: TChineseCalendar
+// Function: ValidDate
+// Arguments: TChineseDate &
+//
+// Comments: This function Determines whether the given
+// date is a valid chinese date
+//
+// Return: TBool - ETrue if date is valid, else EFalse
+//------------------------------------------------------
+TBool TChineseCalendar::ValidDate(const TChineseDate &aDate) const
+ {
+ //do some trivial checks to ensure that the date is in the range of the lookup table
+ if (aDate.iYear==0 || aDate.iYear>KNoOfYearsInCycle)
+ return EFalse;
+
+ if (aDate.iCycle < KFirstCycle)
+ return EFalse;
+
+ if (aDate.iCycle==KFirstCycle && aDate.iYear < KFirstYear)
+ return EFalse;
+
+ if (aDate.iCycle > KLastCycle)
+ return EFalse;
+
+ if ( (aDate.iCycle==KLastCycle) && (aDate.iYear>KLastYear))
+ return EFalse;
+
+ if (aDate.iDay==0 || aDate.iDay>30)
+ return EFalse;
+
+ return ETrue;
+ }
+
+TReal TChineseCalendar::JulianDate() __SOFTFP
+ {
+ return iJulianDay;
+ }