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