pimappsupport/chinesecalendaralg/pluginsrc/gregoriancalendar.cpp
branchRCL_3
changeset 12 38571fd2a704
equal deleted inserted replaced
5:42814f902fe6 12:38571fd2a704
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implementation of the TGregorianCalendar class.
       
    15 //
       
    16 
       
    17 #include <e32std.h>
       
    18 #include <e32math.h>
       
    19 #include "gregoriancalendar.h"
       
    20 
       
    21 // Constants
       
    22 const TReal KFourYears			= 4.0;
       
    23 const TReal KFourHundredYears	= 400;
       
    24 const TReal KOneHundredYears	= 100;
       
    25 const TReal KGregStartEpoch		= 1721424.5;
       
    26 //
       
    27 const TInt KDayOffsetByZero		= 0;
       
    28 const TInt KGregDaysInNormYear	= 365;
       
    29 const TInt KDaysIn400Years		= 146097;
       
    30 const TInt KDaysIn100Years		= 36524;
       
    31 const TInt KDaysIn4Years		= 1461;
       
    32 const TInt KGregCycle			= 12;
       
    33 const TInt KGregLeaps			= 7;
       
    34 const TInt KGregOffset			= 11;
       
    35 const TInt KGregStdMonth		= 30;
       
    36 const TInt KLastDayInDecember	= 31;
       
    37 
       
    38 
       
    39 
       
    40 //////////////////////////////////////////////////////////////////////
       
    41 // Construction/Destruction
       
    42 //////////////////////////////////////////////////////////////////////
       
    43 
       
    44 //------------------------------------------------------
       
    45 // Class:       TGregorianCalendar
       
    46 // Function:    TGregorianCalendar
       
    47 // Arguments:   None
       
    48 //
       
    49 // Comments:    Constructor
       
    50 //
       
    51 // Return:      None
       
    52 //------------------------------------------------------
       
    53 TGregorianCalendar::TGregorianCalendar()
       
    54 	{
       
    55 	InitMembers();
       
    56 	}
       
    57 
       
    58 //------------------------------------------------------
       
    59 // Class:       TGregorianCalendar
       
    60 // Function:    TGregorianCalendar
       
    61 // Arguments:   TReal
       
    62 //
       
    63 // Comments:    Overloaded Constructor
       
    64 //
       
    65 // Return:      None
       
    66 //------------------------------------------------------
       
    67 TGregorianCalendar::TGregorianCalendar(TReal aJD) __SOFTFP
       
    68 	{
       
    69 	iJulianDay = aJD;
       
    70 	InitMembers();
       
    71 	}
       
    72 
       
    73 //------------------------------------------------------
       
    74 // Class:       TGregorianCalendar
       
    75 // Function:    InitMembers
       
    76 // Arguments:   None
       
    77 //
       
    78 // Comments:    This function initialises the member variables
       
    79 //				or the class.  It is called in the constructors
       
    80 //
       
    81 // Return:      
       
    82 //------------------------------------------------------
       
    83 void TGregorianCalendar::InitMembers()
       
    84 	{
       
    85 	iStartEpoch = KGregStartEpoch + KCalConvPointFive;
       
    86 	Floor(iDaysInNormYear,KGregDaysInNormYear);
       
    87 	iCycle = KGregCycle;
       
    88 	iLeaps = KGregLeaps;
       
    89 	iOffset = KGregOffset;
       
    90 	iStdYearMonth = KGregStdMonth;
       
    91 	}
       
    92 
       
    93 //------------------------------------------------------
       
    94 // Class:       TGregorianCalendar
       
    95 // Function:    IsLeapYear
       
    96 // Arguments:   const TInt
       
    97 //
       
    98 // Comments:    Determines whether the given year is a leap year.
       
    99 //
       
   100 // Return:      ETrue if leap year, else EFalse
       
   101 //------------------------------------------------------
       
   102 TBool TGregorianCalendar::IsLeapYear(const TInt aYear)const
       
   103 	{
       
   104 	TReal result;
       
   105 	TBool rtn = EFalse;
       
   106 
       
   107 	Mod(result,aYear,KFourYears);
       
   108 
       
   109 	if	(!result)
       
   110 		{
       
   111 		rtn = ETrue;
       
   112 		}
       
   113 
       
   114 	Mod(result,aYear,KOneHundredYears);
       
   115 
       
   116 	if	(!result)
       
   117 		{
       
   118 		Mod(result,aYear,KFourHundredYears);
       
   119 
       
   120 		if	(result)
       
   121 			{
       
   122 			rtn = EFalse;
       
   123 			}
       
   124 		}
       
   125 	return rtn;
       
   126 	}
       
   127 
       
   128 //------------------------------------------------------
       
   129 // Class:       TGregorianCalendar
       
   130 // Function:    GregToJulianDay
       
   131 // Arguments:   const TArithmeticalDate&
       
   132 //
       
   133 // Comments:    converts gregorian date to Julian day value
       
   134 //
       
   135 // Return:      Julian day value for the given Gregorian date
       
   136 //------------------------------------------------------
       
   137 TReal TGregorianCalendar::GregToJulianDay(const TArithmeticalDate& aDate) const __SOFTFP
       
   138 	{
       
   139 	TReal result;
       
   140 	TReal tempReal;
       
   141 	TInt tempInt;
       
   142 
       
   143 	// days to the start of the year based on normal years
       
   144 	result = iStartEpoch + (iDaysInNormYear * (aDate.iYear - 1));
       
   145 
       
   146 	// leap year corrections
       
   147 	tempReal = (aDate.iYear - 1) / KFourYears;
       
   148 	Floor(tempInt,tempReal);
       
   149 	result += tempInt;
       
   150 
       
   151 	tempReal = (aDate.iYear - 1) / KOneHundredYears;
       
   152 	Floor(tempInt,tempReal);
       
   153 	result -= tempInt;
       
   154 
       
   155 	tempReal = (aDate.iYear - 1) / KFourHundredYears;
       
   156 	Floor(tempInt,tempReal);
       
   157 	result += tempInt;
       
   158 
       
   159 	// days in whole months in the year in question - approx 
       
   160 	// based on Feb having 30 days
       
   161 	tempInt = DaysMonthsElapsed(aDate.iMonth);
       
   162 	result += tempInt;
       
   163 
       
   164 	// correction for assumption that Feb has 30 days
       
   165 	if	(aDate.iMonth <= (EFebruary + 1))
       
   166 		result += KDayOffsetByZero;
       
   167 	else if	(aDate.iMonth > (EFebruary + 1) && IsLeapYear(aDate.iYear))
       
   168 		result -= 1;
       
   169 	else
       
   170 		result -= 2;
       
   171 
       
   172 	// days in month in question
       
   173 	result += aDate.iDay;
       
   174 
       
   175 	return result;
       
   176 	}
       
   177 
       
   178 //------------------------------------------------------
       
   179 // Class:       TGregorianCalendar
       
   180 // Function:    GregorianToDateTime
       
   181 // Arguments:   TDateTime& 
       
   182 //
       
   183 // Comments:    This gets the date from the TGregorianCalendar class
       
   184 //				and places in the the given TDateTime class
       
   185 //
       
   186 // Return:      void
       
   187 //------------------------------------------------------
       
   188 void TGregorianCalendar::GregorianToDateTime(TDateTime& aDT)
       
   189 	{
       
   190 	TArithmeticalDate gregDate;
       
   191 	GregFromJulianDay(gregDate,iJulianDay);
       
   192 
       
   193 	aDT.Set(0,EJanuary,0,0,0,0,0);
       
   194 	aDT.SetMonth((TMonth)(gregDate.iMonth - 1));
       
   195 	aDT.SetDay(gregDate.iDay - 1);
       
   196 	aDT.SetYear(gregDate.iYear);
       
   197 	}
       
   198 
       
   199 //------------------------------------------------------
       
   200 // Class:       TGregorianCalendar
       
   201 // Function:    CalcGregYear
       
   202 // Arguments:   TArithmeticalDate&
       
   203 //
       
   204 // Comments:    Calculates the gregorian year from Julian 
       
   205 //				day value.
       
   206 //
       
   207 // Return:      None
       
   208 //------------------------------------------------------
       
   209 void TGregorianCalendar::CalcGregYear(TArithmeticalDate& aDate, TReal aJulianDay) const __SOFTFP
       
   210 	{
       
   211 	TReal d0;
       
   212 	TReal d1;
       
   213 	TReal d2;
       
   214 	TReal d3;
       
   215 	TReal year;
       
   216 	TInt n400;
       
   217 	TInt n100;
       
   218 	TInt n4;
       
   219 	TInt n1;
       
   220 	TInt32 yearInt32;
       
   221 
       
   222 	// determine year
       
   223 	// get to start of calendar ie year 1
       
   224 	d0 = aJulianDay - iStartEpoch - 1;
       
   225 
       
   226 	Mod(d1,d0,KDaysIn400Years);
       
   227 
       
   228 	Mod(d2,d1,KDaysIn100Years);
       
   229 
       
   230 	Mod(d3,d2,KDaysIn4Years);
       
   231 
       
   232 	// number of 400 year blocks
       
   233 	d0 /= KDaysIn400Years;
       
   234 	Floor(n400,d0);
       
   235 
       
   236 	// number of 100 year blocks
       
   237 	d1 /= KDaysIn100Years;
       
   238 	Floor(n100,d1);
       
   239 
       
   240 	// number of 4 year blocks
       
   241 	d2 /= KDaysIn4Years;
       
   242 	Floor(n4,d2);
       
   243 
       
   244 		// number of 1 year blocks
       
   245 	d3 /= KGregDaysInNormYear;
       
   246 	Floor(n1,d3);
       
   247 
       
   248 	// calc year
       
   249 	year = (KFourHundredYears * n400) + (KOneHundredYears * n100) + (KFourYears * n4) + n1;
       
   250 	Math::Int(yearInt32,year);
       
   251 
       
   252 	if	((n100 == (KFourHundredYears / KOneHundredYears)) || (n1 == KFourYears))
       
   253 		{
       
   254 		aDate.iYear = yearInt32;
       
   255 		}
       
   256 	else
       
   257 		{
       
   258 		aDate.iYear = yearInt32 + 1;
       
   259 		}
       
   260 	}
       
   261 
       
   262 //------------------------------------------------------
       
   263 // Class:       TGregorianCalendar
       
   264 // Function:    GregDateDiff
       
   265 // Arguments:   const TArithmeticalDate, const TArithmeticalDate
       
   266 //
       
   267 // Comments:    This function Determines the difference in days
       
   268 //				between two gregorian dates.
       
   269 //
       
   270 // Return:      Days difference
       
   271 //------------------------------------------------------
       
   272 TInt TGregorianCalendar::GregDateDiff(const TArithmeticalDate aDate1, const TArithmeticalDate aDate2)const
       
   273 	{
       
   274 	TInt diff;
       
   275 	TReal diffReal;
       
   276 	diffReal = GregToJulianDay(aDate2) - GregToJulianDay(aDate1);
       
   277 	Floor(diff,diffReal);
       
   278 	return diff;
       
   279 	}
       
   280 
       
   281 //------------------------------------------------------
       
   282 // Class:       TGregorianCalendar
       
   283 // Function:    DayNumber
       
   284 // Arguments:   const TArithmeticalDate& 
       
   285 //
       
   286 // Comments:    this function returns the number of days that
       
   287 //				have elapsed in the given year
       
   288 //
       
   289 // Return:      see comment
       
   290 //------------------------------------------------------
       
   291 TInt TGregorianCalendar::DayNumber(const TArithmeticalDate& aDate)const
       
   292 	{
       
   293 	TArithmeticalDate tempDate;
       
   294 	TInt dayNum;
       
   295 
       
   296 	tempDate.iDay = KLastDayInDecember;
       
   297 	tempDate.iMonth = EDecember + 1;
       
   298 	tempDate.iYear = aDate.iYear - 1;
       
   299 
       
   300 	dayNum = GregDateDiff(tempDate,aDate);
       
   301 
       
   302 	return dayNum;
       
   303 	}
       
   304 
       
   305 //------------------------------------------------------
       
   306 // Class:       TGregorianCalendar
       
   307 // Function:    GregFromJulianDay
       
   308 // Arguments:   TArithmeticalDate& , TReal
       
   309 //
       
   310 // Comments:    This function converts a gregorian date to
       
   311 //				a julian day
       
   312 //
       
   313 // Return:      void
       
   314 //------------------------------------------------------
       
   315 void TGregorianCalendar::GregFromJulianDay(TArithmeticalDate& aDate, TReal aJulianDay) const __SOFTFP
       
   316 	{
       
   317 	TReal priorDays;
       
   318 	TReal correction;
       
   319 	TReal day;
       
   320 	TReal month;
       
   321 	TInt32 dayInt32;
       
   322 	TInt32 monthInt32;
       
   323 
       
   324 	CalcGregYear(aDate,aJulianDay);
       
   325 
       
   326 	aDate.iDay = 1;
       
   327 	aDate.iMonth = EJanuary + 1;
       
   328 
       
   329 	priorDays = aJulianDay - GregToJulianDay(aDate);
       
   330 
       
   331 	aDate.iMonth = EMarch + 1;
       
   332 
       
   333 	if	(aJulianDay < GregToJulianDay(aDate))
       
   334 		{
       
   335 		correction = KDayOffsetByZero;
       
   336 		}
       
   337 	else if	((aJulianDay >= GregToJulianDay(aDate)) && IsLeapYear(aDate.iYear))
       
   338 		{
       
   339 		correction = 1;
       
   340 		}
       
   341 	else
       
   342 		{
       
   343 		correction = 2;
       
   344 		}
       
   345 
       
   346 	month = priorDays + correction;
       
   347 	Math::Int(monthInt32,month);
       
   348 	monthInt32 = DayMonthInYear(monthInt32);
       
   349 	aDate.iMonth = monthInt32;
       
   350 
       
   351 	day = aJulianDay - GregToJulianDay(aDate) + 1;
       
   352 	Math::Int(dayInt32,day);
       
   353 	aDate.iDay = dayInt32;
       
   354 	}
       
   355 
       
   356 
       
   357 //------------------------------------------------------
       
   358 // Class:       TArithmeticalCalendar
       
   359 // Function:    DaysMonthsElapsed
       
   360 // Arguments:   const TInt ,const TInt ,const TInt , const TInt ,const TInt
       
   361 //
       
   362 // Comments:    The use of this function varies between calendars 
       
   363 //				however since the form of the equation is the same it 
       
   364 //				is represented in this class.  The equation is use to 
       
   365 //				calculate the number of days in whole months of a particular
       
   366 //				year up to a particular date in the Gregorian and 
       
   367 //				Islamic calendars.  The Hebrew calendar uses this
       
   368 //				equation to calculate the number of whole months 
       
   369 //				since the start of the calendar.
       
   370 //				
       
   371 //
       
   372 // Return:      See comments
       
   373 //------------------------------------------------------
       
   374 TInt TGregorianCalendar::DaysMonthsElapsed(const TInt aYear) const
       
   375 	{
       
   376 	TReal tempReal;
       
   377 	TInt result;
       
   378 
       
   379 	tempReal = iOffset * iLeaps;
       
   380 	Mod(tempReal,tempReal,iCycle);
       
   381 	tempReal = ((iLeaps * aYear) - iLeaps + tempReal) / iCycle;
       
   382 	Floor(result,tempReal);
       
   383 	result = result + (iStdYearMonth * (aYear - KCalConvYearOffsetByOne));
       
   384 
       
   385 	return result;
       
   386 	}
       
   387 
       
   388 //------------------------------------------------------
       
   389 // Class:       TArithmeticalCalendar
       
   390 // Function:    DayMonthInYear
       
   391 // Arguments:   None
       
   392 //
       
   393 // Comments:    This function Determines the month based on
       
   394 //				the number of days into the year it is
       
   395 //
       
   396 // Return:      TInt - Month
       
   397 //------------------------------------------------------
       
   398 TInt TGregorianCalendar::DayMonthInYear(const TInt aDays) const
       
   399 	{
       
   400 	TReal tempReal;
       
   401 	TInt result;
       
   402 
       
   403 	tempReal = iLeaps * iOffset;
       
   404 	Mod(tempReal,tempReal,iCycle);
       
   405 	tempReal = (iCycle * aDays) + (iCycle * iStdYearMonth) + iLeaps - KCalConvYearOffsetByOne + iCycle - tempReal;
       
   406 	tempReal = tempReal / ((iCycle * iStdYearMonth) + iLeaps);
       
   407 	Floor(result,tempReal);
       
   408 
       
   409 	return result;
       
   410 	}