pimappsupport/chinesecalendaralg/originalsrc/Gregorian.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 
       
    18 // System includes
       
    19 #include <e32std.h>
       
    20 #include <e32math.h>
       
    21 
       
    22 // User includes
       
    23 #include "calconv.h"
       
    24 
       
    25 // Constants
       
    26 const TReal KFourYears			= 4.0;
       
    27 const TReal KFourHundredYears	= 400;
       
    28 const TReal KOneHundredYears	= 100;
       
    29 const TReal KGregStartEpoch		= 1721424.5;
       
    30 //
       
    31 const TInt KDayOffsetByZero		= 0;
       
    32 const TInt KGregDaysInNormYear	= 365;
       
    33 const TInt KDaysIn400Years		= 146097;
       
    34 const TInt KDaysIn100Years		= 36524;
       
    35 const TInt KDaysIn4Years		= 1461;
       
    36 const TInt KGregCycle			= 12;
       
    37 const TInt KGregLeaps			= 7;
       
    38 const TInt KGregOffset			= 11;
       
    39 const TInt KGregStdMonth		= 30;
       
    40 const TInt KLastDayInDecember	= 31;
       
    41 
       
    42 
       
    43 
       
    44 //
       
    45 // Construction/Destruction
       
    46 //
       
    47 
       
    48 //------------------------------------------------------
       
    49 // Class:       TGregorianCalendar
       
    50 // Function:    TGregorianCalendar
       
    51 // Arguments:   None
       
    52 //
       
    53 // Comments:    Constructor
       
    54 //
       
    55 // Return:      None
       
    56 //------------------------------------------------------
       
    57 EXPORT_C TGregorianCalendar::TGregorianCalendar()
       
    58 	{
       
    59 	InitMembers();
       
    60 	}
       
    61 
       
    62 //------------------------------------------------------
       
    63 // Class:       TGregorianCalendar
       
    64 // Function:    TGregorianCalendar
       
    65 // Arguments:   TReal
       
    66 //
       
    67 // Comments:    Overloaded Constructor
       
    68 //
       
    69 // Return:      None
       
    70 //------------------------------------------------------
       
    71 EXPORT_C TGregorianCalendar::TGregorianCalendar(TReal aJD)
       
    72 	{
       
    73 	iJulianDay = aJD;
       
    74 	InitMembers();
       
    75 	}
       
    76 
       
    77 //------------------------------------------------------
       
    78 // Class:       TGregorianCalendar
       
    79 // Function:    InitMembers
       
    80 // Arguments:   None
       
    81 //
       
    82 // Comments:    This function initialises the member variables
       
    83 //				or the class.  It is called in the constructors
       
    84 //
       
    85 // Return:      
       
    86 //------------------------------------------------------
       
    87 void TGregorianCalendar::InitMembers()
       
    88 	{
       
    89 	iStartEpoch = KGregStartEpoch + KCalConvPointFive;
       
    90 	Floor(iDaysInNormYear,KGregDaysInNormYear);
       
    91 	iCycle = KGregCycle;
       
    92 	iLeaps = KGregLeaps;
       
    93 	iOffset = KGregOffset;
       
    94 	iStdYearMonth = KGregStdMonth;
       
    95 	}
       
    96 
       
    97 //------------------------------------------------------
       
    98 // Class:       TGregorianCalendar
       
    99 // Function:    IsLeapYear
       
   100 // Arguments:   const TInt
       
   101 //
       
   102 // Comments:    Determines whether the given year is a leap year.
       
   103 //
       
   104 // Return:      ETrue if leap year, else EFalse
       
   105 //------------------------------------------------------
       
   106 TBool TGregorianCalendar::IsLeapYear(const TInt aYear)const
       
   107 	{
       
   108 	TReal result;
       
   109 	TBool rtn = EFalse;
       
   110 
       
   111 	Mod(result,aYear,KFourYears);
       
   112 
       
   113 	if	(!result)
       
   114 		{
       
   115 		rtn = ETrue;
       
   116 		}
       
   117 
       
   118 	Mod(result,aYear,KOneHundredYears);
       
   119 
       
   120 	if	(!result)
       
   121 		{
       
   122 		Mod(result,aYear,KFourHundredYears);
       
   123 
       
   124 		if	(result)
       
   125 			{
       
   126 			rtn = EFalse;
       
   127 			}
       
   128 		}
       
   129 	return rtn;
       
   130 	}
       
   131 
       
   132 //------------------------------------------------------
       
   133 // Class:       TGregorianCalendar
       
   134 // Function:    GregToJulianDay
       
   135 // Arguments:   const TArithmeticalDate&
       
   136 //
       
   137 // Comments:    converts gregorian date to Julian day value
       
   138 //
       
   139 // Return:      Julian day value for the given Gregorian date
       
   140 //------------------------------------------------------
       
   141 TReal TGregorianCalendar::GregToJulianDay(const TArithmeticalDate& aDate) const
       
   142 	{
       
   143 	TReal result;
       
   144 	TReal tempReal;
       
   145 	TInt tempInt;
       
   146 
       
   147 	// days to the start of the year based on normal years
       
   148 	result = iStartEpoch + (iDaysInNormYear * (aDate.iYear - 1));
       
   149 
       
   150 	// leap year corrections
       
   151 	tempReal = (aDate.iYear - 1) / KFourYears;
       
   152 	Floor(tempInt,tempReal);
       
   153 	result += tempInt;
       
   154 
       
   155 	tempReal = (aDate.iYear - 1) / KOneHundredYears;
       
   156 	Floor(tempInt,tempReal);
       
   157 	result -= tempInt;
       
   158 
       
   159 	tempReal = (aDate.iYear - 1) / KFourHundredYears;
       
   160 	Floor(tempInt,tempReal);
       
   161 	result += tempInt;
       
   162 
       
   163 	// days in whole months in the year in question - approx 
       
   164 	// based on Feb having 30 days
       
   165 	tempInt = DaysMonthsElapsed(aDate.iMonth);
       
   166 	result += tempInt;
       
   167 
       
   168 	// correction for assumption that Feb has 30 days
       
   169 	if	(aDate.iMonth <= (EFebruary + 1))
       
   170 		result += KDayOffsetByZero;
       
   171 	else if	(aDate.iMonth > (EFebruary + 1) && IsLeapYear(aDate.iYear))
       
   172 		result -= 1;
       
   173 	else
       
   174 		result -= 2;
       
   175 
       
   176 	// days in month in question
       
   177 	result += aDate.iDay;
       
   178 
       
   179 	return result;
       
   180 	}
       
   181 
       
   182 //------------------------------------------------------
       
   183 // Class:       TGregorianCalendar
       
   184 // Function:    SetDate
       
   185 // Arguments:   const TArithmeticalDate&
       
   186 //
       
   187 // Comments:    This function checks that the give date is
       
   188 //				valid and then assigns the corresponding 
       
   189 //				Julian day value to the class
       
   190 //
       
   191 // Return:      None
       
   192 //------------------------------------------------------
       
   193 EXPORT_C TInt TGregorianCalendar::SetDate(TArithmeticalDate& aGregDate)
       
   194 	{
       
   195 	if	(ValidDate(aGregDate)==EFalse)
       
   196 		{
       
   197 		return KCalConInvalidDate;
       
   198 		}
       
   199 	iJulianDay = GregToJulianDay(aGregDate);
       
   200 	return KErrNone;
       
   201 	}
       
   202 
       
   203 //------------------------------------------------------
       
   204 // Class:       TGregorianCalendar
       
   205 // Function:    ValidDate
       
   206 // Arguments:   const TArithmeticalDate& 
       
   207 //
       
   208 // Comments:    this function Determines that the date given
       
   209 //				is of the correct format for the gregorian 
       
   210 //				calendar.
       
   211 //
       
   212 // Return:      TBool - KSuccess if valid date, else KFail
       
   213 //------------------------------------------------------
       
   214 TBool TGregorianCalendar::ValidDate(const TArithmeticalDate& aDate)const
       
   215 	{
       
   216 
       
   217 	TReal jD;
       
   218 	TArithmeticalDate gregDate;
       
   219 
       
   220 	jD = GregToJulianDay(aDate);
       
   221 	GregFromJulianDay(gregDate,jD);
       
   222 
       
   223 	if	(aDate.operator==(gregDate))
       
   224 		return ETrue;
       
   225 	else
       
   226 		return EFalse;
       
   227 	}
       
   228 
       
   229 //------------------------------------------------------
       
   230 // Class:       TGregorianCalendar
       
   231 // Function:    GetDate
       
   232 // Arguments:   TArithmeticalDate&
       
   233 //
       
   234 // Comments:    Calculates the gregorian date from the 
       
   235 //				Julian day value.
       
   236 //
       
   237 // Return:      None
       
   238 //------------------------------------------------------
       
   239 EXPORT_C void TGregorianCalendar::GetDate(TArithmeticalDate& aDate)
       
   240 	{
       
   241 	GregFromJulianDay(aDate,iJulianDay);
       
   242 	}
       
   243 
       
   244 //------------------------------------------------------
       
   245 // Class:       TGregorianCalendar
       
   246 // Function:    DateTimeToGregorian
       
   247 // Arguments:   TDateTime& 
       
   248 //
       
   249 // Comments:    This function converts a TDateTime class to
       
   250 //				the TGregorianCalendar class
       
   251 //
       
   252 // Return:      void
       
   253 //------------------------------------------------------
       
   254 EXPORT_C void TGregorianCalendar::DateTimeToGregorian(TDateTime& aDT)
       
   255 	{
       
   256 	TArithmeticalDate gregDate;
       
   257 
       
   258 	gregDate.iDay = aDT.Day() + 1;
       
   259 	gregDate.iMonth = (TInt)aDT.Month() + 1;
       
   260 	gregDate.iYear = aDT.Year();
       
   261 
       
   262 	iJulianDay = GregToJulianDay(gregDate);
       
   263 	}
       
   264 
       
   265 //------------------------------------------------------
       
   266 // Class:       TGregorianCalendar
       
   267 // Function:    GregorianToDateTime
       
   268 // Arguments:   TDateTime& 
       
   269 //
       
   270 // Comments:    This gets the date from the TGregorianCalendar class
       
   271 //				and places in the the given TDateTime class
       
   272 //
       
   273 // Return:      void
       
   274 //------------------------------------------------------
       
   275 EXPORT_C void TGregorianCalendar::GregorianToDateTime(TDateTime& aDT)
       
   276 	{
       
   277 	TArithmeticalDate gregDate;
       
   278 
       
   279 	GregFromJulianDay(gregDate,iJulianDay);
       
   280 
       
   281 	aDT.SetMicroSecond(0);
       
   282 	aDT.SetSecond(0);
       
   283 	aDT.SetMinute(0);
       
   284 	aDT.SetHour(0);
       
   285 	aDT.SetMonth((TMonth)(gregDate.iMonth - 1));
       
   286 	aDT.SetDay(gregDate.iDay - 1);
       
   287 	aDT.SetYear(gregDate.iYear);
       
   288 	}
       
   289 
       
   290 //------------------------------------------------------
       
   291 // Class:       TGregorianCalendar
       
   292 // Function:    CalcGregYear
       
   293 // Arguments:   TArithmeticalDate&
       
   294 //
       
   295 // Comments:    Calculates the gregorian year from Julian 
       
   296 //				day value.
       
   297 //
       
   298 // Return:      None
       
   299 //------------------------------------------------------
       
   300 void TGregorianCalendar::CalcGregYear(TArithmeticalDate& aDate, TReal aJulianDay)const
       
   301 	{
       
   302 	TReal d0;
       
   303 	TReal d1;
       
   304 	TReal d2;
       
   305 	TReal d3;
       
   306 	TReal year;
       
   307 	TInt n400;
       
   308 	TInt n100;
       
   309 	TInt n4;
       
   310 	TInt n1;
       
   311 	TInt32 yearInt32;
       
   312 
       
   313 	// determine year
       
   314 	// get to start of calendar ie year 1
       
   315 	d0 = aJulianDay - iStartEpoch - 1;
       
   316 
       
   317 	Mod(d1,d0,KDaysIn400Years);
       
   318 
       
   319 	Mod(d2,d1,KDaysIn100Years);
       
   320 
       
   321 	Mod(d3,d2,KDaysIn4Years);
       
   322 
       
   323 	// number of 400 year blocks
       
   324 	d0 /= KDaysIn400Years;
       
   325 	Floor(n400,d0);
       
   326 
       
   327 	// number of 100 year blocks
       
   328 	d1 /= KDaysIn100Years;
       
   329 	Floor(n100,d1);
       
   330 
       
   331 	// number of 4 year blocks
       
   332 	d2 /= KDaysIn4Years;
       
   333 	Floor(n4,d2);
       
   334 
       
   335 		// number of 1 year blocks
       
   336 	d3 /= KGregDaysInNormYear;
       
   337 	Floor(n1,d3);
       
   338 
       
   339 	// calc year
       
   340 	year = (KFourHundredYears * n400) + (KOneHundredYears * n100) + (KFourYears * n4) + n1;
       
   341 	Math::Int(yearInt32,year);
       
   342 
       
   343 	if	((n100 == (KFourHundredYears / KOneHundredYears)) || (n1 == KFourYears))
       
   344 		{
       
   345 		aDate.iYear = yearInt32;
       
   346 		}
       
   347 	else
       
   348 		{
       
   349 		aDate.iYear = yearInt32 + 1;
       
   350 		}
       
   351 	}
       
   352 
       
   353 //------------------------------------------------------
       
   354 // Class:       TGregorianCalendar
       
   355 // Function:    GregDateDiff
       
   356 // Arguments:   const TArithmeticalDate, const TArithmeticalDate
       
   357 //
       
   358 // Comments:    This function Determines the difference in days
       
   359 //				between two gregorian dates.
       
   360 //
       
   361 // Return:      Days difference
       
   362 //------------------------------------------------------
       
   363 TInt TGregorianCalendar::GregDateDiff(const TArithmeticalDate aDate1, const TArithmeticalDate aDate2)const
       
   364 	{
       
   365 	TInt diff;
       
   366 	TReal diffReal;
       
   367 	diffReal = GregToJulianDay(aDate2) - GregToJulianDay(aDate1);
       
   368 	Floor(diff,diffReal);
       
   369 	return diff;
       
   370 	}
       
   371 
       
   372 //------------------------------------------------------
       
   373 // Class:       TGregorianCalendar
       
   374 // Function:    DayNumber
       
   375 // Arguments:   const TArithmeticalDate& 
       
   376 //
       
   377 // Comments:    this function returns the number of days that
       
   378 //				have elapsed in the given year
       
   379 //
       
   380 // Return:      see comment
       
   381 //------------------------------------------------------
       
   382 TInt TGregorianCalendar::DayNumber(const TArithmeticalDate& aDate)const
       
   383 	{
       
   384 	TArithmeticalDate tempDate;
       
   385 	TInt dayNum;
       
   386 
       
   387 	tempDate.iDay = KLastDayInDecember;
       
   388 	tempDate.iMonth = EDecember + 1;
       
   389 	tempDate.iYear = aDate.iYear - 1;
       
   390 
       
   391 	dayNum = GregDateDiff(tempDate,aDate);
       
   392 
       
   393 	return dayNum;
       
   394 	}
       
   395 
       
   396 //------------------------------------------------------
       
   397 // Class:       TGregorianCalendar
       
   398 // Function:    GregFromJulianDay
       
   399 // Arguments:   TArithmeticalDate& , TReal
       
   400 //
       
   401 // Comments:    This function converts a gregorian date to
       
   402 //				a julian day
       
   403 //
       
   404 // Return:      void
       
   405 //------------------------------------------------------
       
   406 void TGregorianCalendar::GregFromJulianDay(TArithmeticalDate& aDate, TReal aJulianDay)const
       
   407 	{
       
   408 	TReal priorDays;
       
   409 	TReal correction;
       
   410 	TReal day;
       
   411 	TReal month;
       
   412 	TInt32 dayInt32;
       
   413 	TInt32 monthInt32;
       
   414 
       
   415 	CalcGregYear(aDate,aJulianDay);
       
   416 
       
   417 	aDate.iDay = 1;
       
   418 	aDate.iMonth = EJanuary + 1;
       
   419 
       
   420 	priorDays = aJulianDay - GregToJulianDay(aDate);
       
   421 
       
   422 	aDate.iMonth = EMarch + 1;
       
   423 
       
   424 	if	(aJulianDay < GregToJulianDay(aDate))
       
   425 		{
       
   426 		correction = KDayOffsetByZero;
       
   427 		}
       
   428 	else if	((aJulianDay >= GregToJulianDay(aDate)) && IsLeapYear(aDate.iYear))
       
   429 		{
       
   430 		correction = 1;
       
   431 		}
       
   432 	else
       
   433 		{
       
   434 		correction = 2;
       
   435 		}
       
   436 
       
   437 	month = priorDays + correction;
       
   438 	Math::Int(monthInt32,month);
       
   439 	monthInt32 = DayMonthInYear(monthInt32);
       
   440 	aDate.iMonth = monthInt32;
       
   441 
       
   442 	day = aJulianDay - GregToJulianDay(aDate) + 1;
       
   443 	Math::Int(dayInt32,day);
       
   444 	aDate.iDay = dayInt32;
       
   445 	}