Merge "Applied sizeof operator on fixed sized array to calculate size." into tizen_2.2
[platform/framework/native/appfw.git] / src / base / FBaseDateTime.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FBaseDateTime.cpp
19  * @brief               This file contains implementation of DateTime class
20  */
21 #include <stdlib.h>
22 #include <wchar.h>
23 #include <FBaseDateTime.h>
24 #include <FBaseResult.h>
25 #include <FBaseSysLog.h>
26 #include <unique_ptr.h>
27
28 namespace Tizen { namespace Base
29 {
30
31 enum DateTimeLimits
32 {
33         MIN_YEAR = 1,
34         MIN_MONTH = 1,
35         MIN_DAY = 1,
36         MIN_HOUR = 0,
37         MIN_MINUTE = 0,
38         MIN_SECOND = 0,
39         MIN_TICK = 0,
40         _MAX_YEAR = 9999,
41         MAX_MONTH = 12,
42         MAX_DAY = 31,
43         MAX_HOUR = 23,
44         MAX_MINUTE = 59,
45         MAX_SECOND = 59,
46         MAX_TICK = 999,
47         NUM_OF_SEC_IN_DAY = 86400,
48         NUM_OF_SEC_IN_HOUR = 3600,
49         NUM_OF_SEC_IN_MINUTE = 60,
50         NUM_OF_TICKS_IN_DAY = 86400000LL,
51         NUM_OF_TICKS_IN_HOUR = 3600000LL,
52         NUM_OF_TICKS_IN_MINUTE = 60000LL,
53         NUM_OF_TICKS_IN_SECOND = 1000LL
54 };
55
56 static const int TICKS_PER_MILLISECOND = 1;
57 static const int DAYS_IN_LEAP_YEAR[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
58 static const int DAYS[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
59 static const int INT_HALF_BIT = 16;
60 static const int LOW_16BIT = 0xFFFF;
61 static const long long TOTAL_MAX_TICKS = DateTime::GetMaxValue().GetTicks();
62
63 DateTime::DateTime(void)
64         : __pDateTimeImpl(null)
65 {
66         SetValue(MIN_YEAR, MIN_MONTH, MIN_DAY, MIN_HOUR, MIN_MINUTE, MIN_SECOND);
67 }
68
69 DateTime::DateTime(const DateTime& value)
70         : __pDateTimeImpl(null)
71 {
72         SetValue(value);
73 }
74
75 DateTime::~DateTime(void)
76 {
77 }
78
79 result
80 DateTime::SetValue(const TimeSpan& value)
81 {
82         long long total = value.GetTicks();
83         SysTryReturn(NID_BASE, total >= MIN_TICK, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
84                 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
85
86         SysTryReturn(NID_BASE, total <= TOTAL_MAX_TICKS, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
87                 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
88
89         return ConvertTicksToDate(total, &__dateTime);
90 }
91
92 void
93 DateTime::SetValue(const DateTime& value)
94 {
95         __dateTime.year = value.__dateTime.year;
96         __dateTime.month = value.__dateTime.month;
97         __dateTime.day = value.__dateTime.day;
98         __dateTime.hour = value.__dateTime.hour;
99         __dateTime.minute = value.__dateTime.minute;
100         __dateTime.second = value.__dateTime.second;
101 }
102
103 result
104 DateTime::SetValue(int year, int month, int day, int hour, int minute, int second)
105 {
106         SysTryReturn(NID_BASE,
107                 ((year >= MIN_YEAR && year <= _MAX_YEAR) &&
108                 (month >= MIN_MONTH && month <= MAX_MONTH) &&
109                 (hour >= MIN_HOUR && hour <= MAX_HOUR) &&
110                 (minute >= MIN_MINUTE && minute <= MAX_MINUTE) &&
111                 ((second & LOW_16BIT) >= MIN_SECOND && (second & LOW_16BIT) <= MAX_SECOND) &&
112                 ((second >> INT_HALF_BIT) >= MIN_TICK && (second >> INT_HALF_BIT) <= MAX_TICK)),
113                 E_OUT_OF_RANGE, E_OUT_OF_RANGE,
114                 "[%s] One of the year(%d), month(%d), day(%d), hour(%d), minute(%d), second(%d) and tick(%d) is out of allowable range.",
115                 GetErrorMessage(E_OUT_OF_RANGE), year, month, day, hour, minute, second & LOW_16BIT, second >> INT_HALF_BIT);
116
117         int daysInMonth = 0;
118         result r = GetDaysInMonth(year, month, daysInMonth);
119         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
120         SysTryReturn(NID_BASE, (day >= MIN_DAY && day <= daysInMonth), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
121                 ("[%s] day is out of allowable range."), GetErrorMessage(E_OUT_OF_RANGE));
122
123         __dateTime.year = year;
124         __dateTime.month = month;
125         __dateTime.day = day;
126         __dateTime.hour = hour;
127         __dateTime.minute = minute;
128         __dateTime.second = second;
129         return E_SUCCESS;
130 }
131
132 result
133 DateTime::SetValue(int year, int month, int day, int hour, int minute, int second, int millisecond)
134 {
135         SysTryReturn(NID_BASE,
136                 ((year >= MIN_YEAR && year <= _MAX_YEAR) &&
137                 (month >= MIN_MONTH && month <= MAX_MONTH) &&
138                 (hour >= MIN_HOUR && hour <= MAX_HOUR) &&
139                 (minute >= MIN_MINUTE && minute <= MAX_MINUTE) &&
140                 (second >= MIN_SECOND && second <= MAX_SECOND) &&
141                 ((millisecond * TICKS_PER_MILLISECOND >= MIN_TICK) && (millisecond * TICKS_PER_MILLISECOND <= MAX_TICK))),
142                 E_OUT_OF_RANGE, E_OUT_OF_RANGE,
143                 "[%s] One of the year(%d), month(%d), day(%d), hour(%d), minute(%d), second(%d) and tick(%d) is out of allowable range.",
144                 GetErrorMessage(E_OUT_OF_RANGE), year, month, day, hour, minute, second, millisecond * TICKS_PER_MILLISECOND);
145
146         int daysInMonth = 0;
147         result r = GetDaysInMonth(year, month, daysInMonth);
148         SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
149         SysTryReturn(NID_BASE, (day >= MIN_DAY && day <= daysInMonth), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
150                 ("[%s] day is out of allowable range."), GetErrorMessage(E_OUT_OF_RANGE));
151
152         __dateTime.year = year;
153         __dateTime.month = month;
154         __dateTime.day = day;
155         __dateTime.hour = hour;
156         __dateTime.minute = minute;
157         __dateTime.second = ((millisecond * TICKS_PER_MILLISECOND) << INT_HALF_BIT) | second;
158         return E_SUCCESS;
159 }
160
161 result
162 DateTime::SetValue(long long ticks)
163 {
164         return ConvertTicksToDate(ticks, &__dateTime);
165 }
166
167 DateTime&
168 DateTime::operator =(const DateTime& rhs)
169 {
170         if (&rhs != this)
171         {
172                 SetValue(rhs);
173         }
174
175         return *this;
176 }
177
178 bool
179 DateTime::operator ==(const DateTime& rhs) const
180 {
181         return((__dateTime.year == rhs.__dateTime.year) && (__dateTime.month == rhs.__dateTime.month)
182                 && (__dateTime.day == rhs.__dateTime.day) && (__dateTime.hour == rhs.__dateTime.hour) &&
183                 (__dateTime.minute == rhs.__dateTime.minute) && (__dateTime.second == rhs.__dateTime.second));
184 }
185
186 bool
187 DateTime::operator !=(const DateTime& rhs) const
188 {
189         return !(*this == rhs);
190 }
191
192 bool
193 DateTime::operator <(const DateTime& rhs) const
194 {
195         if (__dateTime.year < rhs.__dateTime.year)
196         {
197                 return true;
198         }
199         if (__dateTime.year > rhs.__dateTime.year)
200         {
201                 return false;
202         }
203         if (__dateTime.month < rhs.__dateTime.month)
204         {
205                 return true;
206         }
207         if (__dateTime.month > rhs.__dateTime.month)
208         {
209                 return false;
210         }
211         if (__dateTime.day < rhs.__dateTime.day)
212         {
213                 return true;
214         }
215         if (__dateTime.day > rhs.__dateTime.day)
216         {
217                 return false;
218         }
219         if (__dateTime.hour < rhs.__dateTime.hour)
220         {
221                 return true;
222         }
223         if (__dateTime.hour > rhs.__dateTime.hour)
224         {
225                 return false;
226         }
227         if (__dateTime.minute < rhs.__dateTime.minute)
228         {
229                 return true;
230         }
231         if (__dateTime.minute > rhs.__dateTime.minute)
232         {
233                 return false;
234         }
235         if ((__dateTime.second & LOW_16BIT) < (rhs.__dateTime.second & LOW_16BIT))
236         {
237                 return true;
238         }
239         if ((__dateTime.second & LOW_16BIT) > (rhs.__dateTime.second & LOW_16BIT))
240         {
241                 return false;
242         }
243         if ((__dateTime.second >> INT_HALF_BIT) < (rhs.__dateTime.second >> INT_HALF_BIT))
244         {
245                 return true;
246         }
247
248         return false;
249 }
250
251 bool
252 DateTime::operator >(const DateTime& rhs) const
253 {
254         if (__dateTime.year > rhs.__dateTime.year)
255         {
256                 return true;
257         }
258         if (__dateTime.year < rhs.__dateTime.year)
259         {
260                 return false;
261         }
262         if (__dateTime.month > rhs.__dateTime.month)
263         {
264                 return true;
265         }
266         if (__dateTime.month < rhs.__dateTime.month)
267         {
268                 return false;
269         }
270         if (__dateTime.day > rhs.__dateTime.day)
271         {
272                 return true;
273         }
274         if (__dateTime.day < rhs.__dateTime.day)
275         {
276                 return false;
277         }
278         if (__dateTime.hour > rhs.__dateTime.hour)
279         {
280                 return true;
281         }
282         if (__dateTime.hour < rhs.__dateTime.hour)
283         {
284                 return false;
285         }
286         if (__dateTime.minute > rhs.__dateTime.minute)
287         {
288                 return true;
289         }
290         if (__dateTime.minute < rhs.__dateTime.minute)
291         {
292                 return false;
293         }
294         if ((__dateTime.second & LOW_16BIT) > (rhs.__dateTime.second & LOW_16BIT))
295         {
296                 return true;
297         }
298         if ((__dateTime.second & LOW_16BIT) < (rhs.__dateTime.second & LOW_16BIT))
299         {
300                 return false;
301         }
302         if ((__dateTime.second >> INT_HALF_BIT) > (rhs.__dateTime.second >> INT_HALF_BIT))
303         {
304                 return true;
305         }
306
307         return false;
308 }
309
310 bool
311 DateTime::operator <=(const DateTime& rhs) const
312 {
313         return ((*this == rhs) || (*this < rhs));
314 }
315
316 bool
317 DateTime::operator >=(const DateTime& rhs) const
318 {
319         return ((*this == rhs) || (*this > rhs));
320 }
321
322 result
323 DateTime::Add(const TimeSpan& t)
324 {
325         result r = AddTicks(t.GetTicks());
326         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
327
328         return r;
329 }
330
331 result
332 DateTime::AddDays(int days)
333 {
334         long long ticks = static_cast< long long >(days) * NUM_OF_TICKS_IN_DAY;
335
336         result r = AddTicks(ticks);
337         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
338
339         return r;
340 }
341
342 result
343 DateTime::AddHours(int hours)
344 {
345         long long ticks = static_cast< long long >(hours) * NUM_OF_TICKS_IN_HOUR;
346
347         result r = AddTicks(ticks);
348         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
349
350         return r;
351 }
352
353 result
354 DateTime::AddMinutes(int minutes)
355 {
356         long long ticks = static_cast< long long >(minutes) * NUM_OF_TICKS_IN_MINUTE;
357
358         result r = AddTicks(ticks);
359         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
360
361         return r;
362 }
363
364 result
365 DateTime::AddMonths(int months)
366 {
367         DateTime tmp;
368         tmp.SetValue(*this);
369
370         tmp.__dateTime.year += months / MAX_MONTH; // Get the year to add
371
372         int tempMonth = tmp.__dateTime.month + months % MAX_MONTH;
373         if (tempMonth > MAX_MONTH)  // Month was added and moved to next year
374         {
375                 tmp.__dateTime.year++;
376                 tmp.__dateTime.month = tempMonth - MAX_MONTH;
377         }
378         else if (tempMonth <= 0)    // Month was subtracted and moved to previous year
379         {
380                 tmp.__dateTime.year--;
381                 tmp.__dateTime.month = MAX_MONTH + tempMonth;
382         }
383         else                        // Keep current year
384         {
385                 tmp.__dateTime.month += months % MAX_MONTH;
386         }
387
388         // Check the days in Month
389         if (tmp.__dateTime.month != 2)      // Current month is not Feb
390         {
391                 if (tmp.__dateTime.day == 31)   // Previous day is 31th
392                 {
393                         result r = SetValue(tmp.__dateTime.year, tmp.__dateTime.month, tmp.__dateTime.day);
394                         if (IsFailed(r))            // Current month doesn't have 31th
395                         {
396                                 tmp.__dateTime.day = 30;    // Set day to 30th
397                         }
398                 }
399         }
400         else                                    // Current month is Feb
401         {
402                 if (tmp.__dateTime.day > 28)        // Previous day is over 28th
403                 {
404                         if (tmp.IsLeapYear())           // Leap year
405                         {
406                                 tmp.__dateTime.day = 29;    // Set day to 29th
407                         }
408                         else                            // Not leap year
409                         {
410                                 tmp.__dateTime.day = 28;    // Set day to 28th
411                         }
412                 }
413         }
414
415         SysTryReturn(NID_BASE, (tmp <= DateTime::GetMaxValue()) && (tmp >= DateTime::GetMinValue()), E_OUT_OF_RANGE,
416                 E_OUT_OF_RANGE, "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
417
418         SetValue(tmp);
419
420         return E_SUCCESS;
421 }
422
423 result
424 DateTime::AddSeconds(int seconds)
425 {
426         long long ticks = static_cast< long long >(seconds) * NUM_OF_TICKS_IN_SECOND;
427
428         result r = AddTicks(ticks);
429         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
430
431         return r;
432 }
433
434 result
435 DateTime::AddMilliseconds(long long milliseconds)
436 {
437         long long ticks = milliseconds * TICKS_PER_MILLISECOND;
438
439         result r = AddTicks(ticks);
440         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
441
442         return r;
443 }
444
445 result
446 DateTime::AddTicks(long long ticks)
447 {
448         long long total = ConvertDateToTicks(&__dateTime);
449         total += ticks;
450
451         result r = ConvertTicksToDate(total, &__dateTime);
452         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
453
454         return r;
455 }
456
457 result
458 DateTime::AddYears(int years)
459 {
460         DateTime tmp;
461         tmp.SetValue(*this);
462
463         int sum = years + tmp.__dateTime.year;
464
465         SysTryReturn(NID_BASE, (sum >= MIN_YEAR && sum <= _MAX_YEAR), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
466                 "[%s] The years(%d) + current year(%d) MUST be within the %d and %d (inclusive).",
467                 GetErrorMessage(E_OUT_OF_RANGE), years, __dateTime.year, MIN_YEAR, _MAX_YEAR);
468
469         tmp.__dateTime.year = sum;
470
471         // Check the days in Month
472         if (tmp.__dateTime.month == 2)      // Feb
473         {
474                 if (tmp.__dateTime.day > 28)
475                 {
476                         if (tmp.IsLeapYear())       // Check the leap year
477                         {
478                                 tmp.__dateTime.day = 29;
479                         }
480                         else
481                         {
482                                 tmp.__dateTime.day = 28;
483                         }
484                 }
485         }
486
487         SetValue(tmp);
488
489         return E_SUCCESS;
490 }
491
492 int
493 DateTime::Compare(const DateTime& dt1, const DateTime& dt2)
494 {
495         if (dt1 > dt2)
496         {
497                 return 1;
498         }
499         else if (dt1 < dt2)
500         {
501                 return -1;
502         }
503
504         return 0;
505 }
506
507 int
508 DateTime::CompareTo(const DateTime& value) const
509 {
510         return DateTime::Compare(*this, value);
511 }
512
513 bool
514 DateTime::Equals(const Object& obj) const
515 {
516         const DateTime* pOther = dynamic_cast< const DateTime* >(&obj);
517         if (pOther == null)
518         {
519                 return false;
520         }
521
522         return (*this == *pOther);
523 }
524
525 int
526 DateTime::GetHashCode(void) const
527 {
528         TimeSpan t = GetTime();
529         int hash = t.GetHashCode();
530         return (hash ^ (hash >> INT_HALF_BIT));
531 }
532
533 TimeSpan
534 DateTime::GetTimeOfDay(void) const
535 {
536         long long total = ConvertDateToSeconds(&__dateTime);
537
538         TmDateTime midnight;
539         midnight.year = __dateTime.year;
540         midnight.month = __dateTime.month;
541         midnight.day = __dateTime.day;
542         midnight.hour = MIN_HOUR;
543         midnight.minute = MIN_MINUTE;
544         midnight.second = MIN_SECOND;
545
546         long long since = ConvertDateToSeconds(&midnight);
547
548         long long span = total - since;
549
550         return (TimeSpan(span * NUM_OF_TICKS_IN_SECOND));
551 }
552
553 result
554 DateTime::GetDaysInMonth(int year, int month, int& days)
555 {
556         const static int daysInMonth[] = { 0xFF, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
557
558         SysTryReturn(NID_BASE, (year >= MIN_YEAR && year <= _MAX_YEAR), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
559                 "[%s] The year(%d) MUST be within the %d and %d (inclusive).", GetErrorMessage(E_OUT_OF_RANGE),
560                 year, MIN_YEAR, _MAX_YEAR);
561         SysTryReturn(NID_BASE, (month >= MIN_MONTH && month <= MAX_MONTH), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
562                 "[%s] The month(%d) MUST be within the %d and %d (inclusive).", GetErrorMessage(E_OUT_OF_RANGE),
563                 month, MIN_MONTH, MAX_MONTH);
564
565         if (DateTime::IsLeapYear(year) && month == 2)
566         {
567                 days = daysInMonth[month] + 1;
568         }
569         else
570         {
571                 days = daysInMonth[month];
572         }
573
574         return E_SUCCESS;
575 }
576
577 result
578 DateTime::Subtract(const TimeSpan& t)
579 {
580         DateTime dt1;
581         long long total = ConvertDateToTicks(&__dateTime);
582         long long span = total - t.GetTicks();
583
584         SysTryReturn(NID_BASE, span >= MIN_TICK, E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[%s] The arguments contain invalid values.",
585                 GetErrorMessage(E_OUT_OF_RANGE));
586
587         SysTryReturn(NID_BASE, span <= TOTAL_MAX_TICKS, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
588                 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
589
590         result r = ConvertTicksToDate(span, &__dateTime);
591         SysTryReturnResult(NID_BASE, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
592
593         return r;
594 }
595
596 String
597 DateTime::ToString(void) const
598 {
599         wchar_t date[] = L"01/01/1970 00:00:00";
600
601         swprintf(date, (sizeof(date) / sizeof(wchar_t)), L"%2d/%2d/%4d %2d:%2d:%2d",
602                 __dateTime.month, __dateTime.day, __dateTime.year, __dateTime.hour, __dateTime.minute,
603                 (__dateTime.second & LOW_16BIT));
604
605         if (__dateTime.month < 10)
606         {
607                 date[0] = L'0';
608         }
609
610         if (__dateTime.day < 10)
611         {
612                 date[3] = L'0';
613         }
614
615         if (__dateTime.year < 10)
616         {
617                 date[6] = L'0';
618                 date[7] = L'0';
619                 date[8] = L'0';
620         }
621         else if (__dateTime.year < 100)
622         {
623                 date[6] = L'0';
624                 date[7] = L'0';
625         }
626         else if (__dateTime.year < 1000)
627         {
628                 date[6] = L'0';
629         }
630
631         if (__dateTime.hour < 10)
632         {
633                 date[11] = L'0';
634         }
635
636         if (__dateTime.minute < 10)
637         {
638                 date[14] = L'0';
639         }
640
641         if ((__dateTime.second & LOW_16BIT) < 10)
642         {
643                 date[17] = L'0';
644         }
645
646         return String(date);
647 }
648
649 result
650 DateTime::Parse(const String& str, DateTime& dt)
651 {
652         SysTryReturn(NID_BASE,
653                 (str.GetLength() == 19
654                 && str[2] == L'/' && str[5] == L'/' && str[10] == L' ' && str[13] == L':' && str[16] == L':'),
655                 E_INVALID_FORMAT, E_INVALID_FORMAT, ("[%s] The str(%s) is not formatted like 'mm/dd/yyyy hh:mm:ss'."),
656                 GetErrorMessage(E_INVALID_FORMAT), str.GetPointer());
657
658         std::unique_ptr< wchar_t[] > pTmp(new (std::nothrow) wchar_t[5]);
659         SysTryReturn(NID_BASE, pTmp != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
660                 GetErrorMessage(E_OUT_OF_MEMORY));
661
662         wchar_t* pMchar = const_cast< wchar_t* >(str.GetPointer());
663
664         // month
665         wcsncpy(pTmp.get(), pMchar, 2);
666         pTmp[2] = L'\0';
667
668         int month = static_cast< int >(wcstol(pTmp.get(), null, 10));
669
670         // day
671         wcsncpy(pTmp.get(), pMchar + 3, 2);
672         pTmp[2] = L'\0';
673
674         int day = static_cast< int >(wcstol(pTmp.get(), null, 10));
675
676         // year
677         wcsncpy(pTmp.get(), pMchar + 6, 4);
678         pTmp[4] = L'\0';
679
680         int year = static_cast< int >(wcstol(pTmp.get(), null, 10));
681
682         // hour
683         wcsncpy(pTmp.get(), pMchar + 11, 2);
684         pTmp[2] = L'\0';
685
686         int hour = static_cast< int >(wcstol(pTmp.get(), null, 10));
687
688         // minute
689         wcsncpy(pTmp.get(), pMchar + 14, 2);
690         pTmp[2] = L'\0';
691
692         int minute = static_cast< int >(wcstol(pTmp.get(), null, 10));
693
694         // second
695         wcsncpy(pTmp.get(), pMchar + 17, 2);
696         pTmp[2] = L'\0';
697
698         int sec = static_cast< int >(wcstol(pTmp.get(), null, 10));
699
700         // construct date time
701         DateTime tmpDt;
702         result r = tmpDt.SetValue(year, month, day, hour, minute, sec);
703         SysTryReturnResult(NID_BASE, !IsFailed(r), r, ("[%s] Propagating."), GetErrorMessage(r));
704
705         dt.SetValue(tmpDt);
706
707         return E_SUCCESS;
708 }
709
710 int
711 DateTime::GetYear(void) const
712 {
713         return __dateTime.year;
714 }
715
716 int
717 DateTime::GetMonth(void) const
718 {
719         return __dateTime.month;
720 }
721
722 int
723 DateTime::GetDay(void) const
724 {
725         return __dateTime.day;
726 }
727
728 int
729 DateTime::GetHour(void) const
730 {
731         return __dateTime.hour;
732 }
733
734 int
735 DateTime::GetMinute(void) const
736 {
737         return __dateTime.minute;
738 }
739
740 int
741 DateTime::GetSecond(void) const
742 {
743         return (__dateTime.second & LOW_16BIT);
744 }
745
746 int
747 DateTime::GetMillisecond(void) const
748 {
749         return ((__dateTime.second >> INT_HALF_BIT) / TICKS_PER_MILLISECOND);
750 }
751
752 long long
753 DateTime::GetTicks(void) const
754 {
755         return ConvertDateToTicks(&__dateTime);
756 }
757
758 int
759 DateTime::GetTicksPerSecond(void)
760 {
761         return NUM_OF_TICKS_IN_SECOND;
762 }
763
764 TimeSpan
765 DateTime::GetTime(void) const
766 {
767         long long seconds = ConvertDateToSeconds(&__dateTime) - ConvertDateToSeconds(&(DateTime::GetMinValue().__dateTime));
768
769         return TimeSpan(seconds * NUM_OF_TICKS_IN_SECOND);
770 }
771
772 const DateTime&
773 DateTime::GetMaxValue(void)
774 {
775         static DateTime maxValue(_MAX_YEAR, MAX_MONTH, MAX_DAY, MAX_HOUR, MAX_MINUTE, MAX_SECOND, MAX_TICK);
776
777         return maxValue;
778 }
779
780 const DateTime&
781 DateTime::GetMinValue(void)
782 {
783         static DateTime minValue(MIN_YEAR, MIN_MONTH, MIN_DAY, MIN_HOUR, MIN_MINUTE, MIN_SECOND, MIN_TICK);
784
785         return minValue;
786 }
787
788 bool
789 DateTime::IsLeapYear(void) const
790 {
791         return DateTime::IsLeapYear(__dateTime.year);
792 }
793
794 bool
795 DateTime::IsLeapYear(int year)
796 {
797         return year >= 0 && (!(year % 4) && ((year % 100) || !(year % 400)));
798 }
799
800 DateTime::DateTime(int year, int month, int day, int hour, int minute, int second, int tick)
801         : __pDateTimeImpl(null)
802 {
803         SetValue(year, month, day, hour, minute, (tick << INT_HALF_BIT) | second);
804 }
805
806 result
807 DateTime::ConvertTicksToDate(long long ticks, TmDateTime* pDateTime)
808 {
809         SysTryReturnResult(NID_BASE, (ticks >= MIN_TICK) && (ticks <= TOTAL_MAX_TICKS), E_OUT_OF_RANGE,
810                 "[%s] The arguments (%lld) contain invalid values.", GetErrorMessage(E_OUT_OF_RANGE), ticks);
811
812         int month = 0;
813         int day = 0;
814         int hour = 0;
815         int minute = 0;
816         int second = 0;
817         int tempTicks = 0;
818
819         int totalDays = static_cast< int >(ticks / NUM_OF_TICKS_IN_DAY) + 1;
820
821         // Get a year and leapYear
822         int year = CountYears(totalDays);
823
824         // Check a leapYear
825         bool leapYear = DateTime::IsLeapYear(year);
826
827         // Get days without year;
828         int tempDays = totalDays - CountDays(year);
829
830         // Get month
831         if (tempDays == 0)      //  month = 0 , day = 0
832         {
833                 month = 0;
834                 day = 0;
835         }
836         else if (leapYear)
837         {
838                 int idx = 0;
839
840                 for (; idx < 12; ++idx)
841                 {
842                         if ((DAYS_IN_LEAP_YEAR[idx] < tempDays) && (tempDays <= DAYS_IN_LEAP_YEAR[idx + 1]))
843                         {
844                                 break;
845                         }
846                 }
847
848                 month = idx + 1;
849                 day = tempDays - DAYS_IN_LEAP_YEAR[idx];
850         }
851         else
852         {
853                 int idx = 0;
854
855                 for (; idx < 12; ++idx)
856                 {
857                         if ((DAYS[idx] < tempDays) && (tempDays <= DAYS[idx + 1]))
858                         {
859                                 break;
860                         }
861                 }
862
863                 month = idx + 1;
864                 day = tempDays - DAYS[idx];
865         }
866
867         DateTime dt(year, month, day, 0, 0, 0, 0);
868
869         // Get Hour
870         tempTicks = static_cast< int >(ticks - ConvertDateToTicks(&(dt.__dateTime)));
871         hour = tempTicks / NUM_OF_TICKS_IN_HOUR;
872
873         // Get Minute
874         tempTicks -= hour * NUM_OF_TICKS_IN_HOUR;
875         minute = tempTicks / NUM_OF_TICKS_IN_MINUTE;
876
877         // Get Second
878         tempTicks -= minute * NUM_OF_TICKS_IN_MINUTE;
879         second = tempTicks / NUM_OF_TICKS_IN_SECOND;
880
881         // Get Tick
882         tempTicks -= second * NUM_OF_TICKS_IN_SECOND;
883         second = ((tempTicks << INT_HALF_BIT) | second);
884
885         pDateTime->year = year;
886         pDateTime->month = month;
887         pDateTime->day = day;
888         pDateTime->hour = hour;
889         pDateTime->minute = minute;
890         pDateTime->second = second;
891
892         return E_SUCCESS;
893 }
894
895 long long
896 DateTime::ConvertDateToTicks(const TmDateTime* pDateTime) const
897 {
898         long long days = 0;
899         long long ticks = 0;
900
901         // Add year
902         days = CountDays(pDateTime->year);
903
904         // Add month
905         if (pDateTime->month != 0)
906         {
907                 if (DateTime::IsLeapYear(pDateTime->year))
908                 {
909                         days += DAYS_IN_LEAP_YEAR[pDateTime->month - 1];
910                 }
911                 else
912                 {
913                         days += DAYS[pDateTime->month - 1];
914                 }
915         }
916
917         // Add days
918         days += pDateTime->day - 1;
919
920         // Convert to ticks
921         ticks = days * NUM_OF_TICKS_IN_DAY;
922
923         // Add hours
924         ticks += pDateTime->hour * NUM_OF_TICKS_IN_HOUR;
925
926         // Add minutes
927         ticks += pDateTime->minute * NUM_OF_TICKS_IN_MINUTE;
928
929         // Add seconds
930         ticks += ((pDateTime->second) & LOW_16BIT) * NUM_OF_TICKS_IN_SECOND;
931
932         // Add ticks
933         ticks += ((pDateTime->second) >> INT_HALF_BIT);
934
935         return ticks;
936 }
937
938 result
939 DateTime::ConvertSecondsToDate(long long seconds, TmDateTime* pDateTime)
940 {
941         long long ticks = seconds * NUM_OF_TICKS_IN_SECOND;
942
943         return ConvertTicksToDate(ticks, pDateTime);
944 }
945
946 long long
947 DateTime::ConvertDateToSeconds(const TmDateTime* pDateTime) const
948 {
949         long long ticks = ConvertDateToTicks(pDateTime);
950
951         return ticks / NUM_OF_TICKS_IN_SECOND;
952 }
953
954 }} // Tizen::Base