|
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 } |