2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FBaseDateTime.cpp
20 * @brief This file contains implementation of DateTime class
25 #include <FBaseDateTime.h>
26 #include <FBaseResult.h>
27 #include <FBaseSysLog.h>
28 #include <unique_ptr.h>
31 namespace Tizen { namespace Base
48 NUM_OF_SEC_IN_DAY = 86400,
49 NUM_OF_SEC_IN_HOUR = 3600,
50 NUM_OF_SEC_IN_MINUTE = 60,
51 NUM_OF_MILLISEC_IN_DAY = 86400000LL,
52 NUM_OF_MILLISEC_IN_HOUR = 3600000LL,
53 NUM_OF_MILLISEC_IN_MINUTE = 60000LL
56 static const long SEC_IN_A_DAY = (24L * 60L * 60L);
57 static const long long MINIMUM_VALUE_IN_SEC = 86400LL;
58 static const int DAYS_IN_LEAP_YEAR[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
59 static const int DAYS[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
61 DateTime::DateTime(void)
62 : __pDateTimeImpl(null)
64 SetValue(MIN_YEAR, MIN_MONTH, MIN_DAY, MIN_HOUR, MIN_MINUTE, MIN_SECOND);
67 DateTime::DateTime(const DateTime& value)
68 : __pDateTimeImpl(null)
73 DateTime::~DateTime(void)
78 DateTime::SetValue(const TimeSpan& value)
80 long long total = (long long) (value.GetTicks() / 1000) + MINIMUM_VALUE_IN_SEC;
81 SysTryReturn(NID_BASE, total >= NUM_OF_SEC_IN_DAY, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
82 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
84 long long maxSeconds = (long long) (DateTime::GetMaxValue().GetTime().GetTicks() / 1000) + MINIMUM_VALUE_IN_SEC;
85 SysTryReturn(NID_BASE, total <= maxSeconds, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
86 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
88 return ConvertSecondsToDate(total, &__dateTime);
92 DateTime::SetValue(const DateTime& value)
94 __dateTime.year = value.__dateTime.year;
95 __dateTime.month = value.__dateTime.month;
96 __dateTime.day = value.__dateTime.day;
97 __dateTime.hour = value.__dateTime.hour;
98 __dateTime.minute = value.__dateTime.minute;
99 __dateTime.second = value.__dateTime.second;
103 DateTime::SetValue(int year, int month, int day, int hour, int minute, int second)
105 SysTryReturn(NID_BASE,
106 ((year >= MIN_YEAR && year <= _MAX_YEAR) &&
107 (month >= MIN_MONTH && month <= MAX_MONTH) &&
108 (hour >= MIN_HOUR && hour <= MAX_HOUR) &&
109 (minute >= MIN_MINUTE && minute <= MAX_MINUTE) &&
110 (second >= MIN_SECOND && second <= MAX_SECOND)),
111 E_OUT_OF_RANGE, E_OUT_OF_RANGE,
112 "[%s] One of the year(%d), month(%d), day(%d), hour(%d), minute(%d), and second(%d) is in out of allowable range.",
113 GetErrorMessage(E_OUT_OF_RANGE), year, month, day, hour, minute, second);
116 result r = GetDaysInMonth(year, month, daysInMonth);
117 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
118 SysTryReturn(NID_BASE, (day >= MIN_DAY && day <= daysInMonth), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
119 ("[%s] day is in out of allowable range."), GetErrorMessage(E_OUT_OF_RANGE));
121 __dateTime.year = year;
122 __dateTime.month = month;
123 __dateTime.day = day;
124 __dateTime.hour = hour;
125 __dateTime.minute = minute;
126 __dateTime.second = second;
132 DateTime::operator =(const DateTime& rhs)
143 DateTime::operator ==(const DateTime& rhs) const
145 return((__dateTime.year == rhs.__dateTime.year) && (__dateTime.month == rhs.__dateTime.month)
146 && (__dateTime.day == rhs.__dateTime.day) && (__dateTime.hour == rhs.__dateTime.hour) &&
147 (__dateTime.minute == rhs.__dateTime.minute) && (__dateTime.second == rhs.__dateTime.second));
151 DateTime::operator !=(const DateTime& rhs) const
153 return !(*this == rhs);
157 DateTime::operator <(const DateTime& rhs) const
159 if (__dateTime.year < rhs.__dateTime.year)
163 if (__dateTime.year > rhs.__dateTime.year)
167 if (__dateTime.month < rhs.__dateTime.month)
171 if (__dateTime.month > rhs.__dateTime.month)
175 if (__dateTime.day < rhs.__dateTime.day)
179 if (__dateTime.day > rhs.__dateTime.day)
183 if (__dateTime.hour < rhs.__dateTime.hour)
187 if (__dateTime.hour > rhs.__dateTime.hour)
191 if (__dateTime.minute < rhs.__dateTime.minute)
195 if (__dateTime.minute > rhs.__dateTime.minute)
199 if (__dateTime.second < rhs.__dateTime.second)
208 DateTime::operator >(const DateTime& rhs) const
210 if (__dateTime.year > rhs.__dateTime.year)
214 if (__dateTime.year < rhs.__dateTime.year)
218 if (__dateTime.month > rhs.__dateTime.month)
222 if (__dateTime.month < rhs.__dateTime.month)
226 if (__dateTime.day > rhs.__dateTime.day)
230 if (__dateTime.day < rhs.__dateTime.day)
234 if (__dateTime.hour > rhs.__dateTime.hour)
238 if (__dateTime.hour < rhs.__dateTime.hour)
242 if (__dateTime.minute > rhs.__dateTime.minute)
246 if (__dateTime.minute < rhs.__dateTime.minute)
250 if (__dateTime.second > rhs.__dateTime.second)
258 DateTime::operator <=(const DateTime& rhs) const
260 return((*this == rhs) || (*this < rhs));
264 DateTime::operator >=(const DateTime& rhs) const
266 return((*this == rhs) || (*this > rhs));
270 DateTime::Add(const TimeSpan& t)
273 long long seconds = ConvertDateToSeconds(&__dateTime);
274 long long total = (long long) (t.GetTicks() / 1000) + seconds;
276 SysTryReturn(NID_BASE, total >= NUM_OF_SEC_IN_DAY, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
277 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
279 long long maxSeconds = ConvertDateToSeconds(&(DateTime::GetMaxValue().__dateTime));
280 SysTryReturn(NID_BASE, total <= maxSeconds, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
281 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
283 result r = ConvertSecondsToDate(total, &__dateTime);
286 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
293 DateTime::AddDays(int days)
295 TimeSpan ts(days * NUM_OF_SEC_IN_DAY * 1000LL);
300 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
307 DateTime::AddHours(int hours)
309 TimeSpan ts(hours * NUM_OF_SEC_IN_HOUR * 1000LL);
314 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
321 DateTime::AddMinutes(int minutes)
323 TimeSpan ts(minutes * NUM_OF_SEC_IN_MINUTE * 1000LL);
328 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
335 DateTime::AddMonths(int months)
340 tmp.__dateTime.year += months / MAX_MONTH;
342 int tempMonth = tmp.__dateTime.month + months % MAX_MONTH;
343 if (tempMonth > MAX_MONTH)
345 tmp.__dateTime.year++;
346 tmp.__dateTime.month = tempMonth - MAX_MONTH;
348 else if (tempMonth < 0)
350 tmp.__dateTime.year--;
351 tmp.__dateTime.month = MAX_MONTH + tempMonth;
353 else if (tempMonth == 0)
355 tmp.__dateTime.year--;
356 tmp.__dateTime.month = MAX_MONTH;
360 tmp.__dateTime.month += months % MAX_MONTH;
363 // Check the days in Month
364 if (tmp.__dateTime.month != 2) // Not Feb
366 if (tmp.__dateTime.day == 31)
368 result r = SetValue(tmp.__dateTime.year, tmp.__dateTime.month, tmp.__dateTime.day);
372 SysTryReturn(NID_BASE, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
378 if (tmp.__dateTime.day > 28)
380 if (tmp.IsLeapYear())
382 tmp.__dateTime.day = 29;
386 tmp.__dateTime.day = 28;
392 SysTryReturn(NID_BASE, (tmp <= DateTime::GetMaxValue()) && (tmp >= DateTime::GetMinValue()), E_OUT_OF_RANGE,
393 E_OUT_OF_RANGE, "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
401 DateTime::AddSeconds(int seconds)
403 TimeSpan ts(seconds * 1000LL);
408 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
415 DateTime::AddYears(int years)
420 int sum = years + tmp.__dateTime.year;
422 SysTryReturn(NID_BASE, (sum >= MIN_YEAR && sum <= _MAX_YEAR), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
423 "[%s] The years(%d) + current year(%d) MUST be within the %d and %d (inclusive).",
424 GetErrorMessage(E_OUT_OF_RANGE), years, __dateTime.year, MIN_YEAR, _MAX_YEAR);
426 tmp.__dateTime.year = sum;
428 // Check the days in Month
429 if (tmp.__dateTime.month == 2) // Feb
431 if (tmp.__dateTime.day > 28)
433 if (tmp.IsLeapYear()) // Check the leap year
435 tmp.__dateTime.day = 29;
439 tmp.__dateTime.day = 28;
450 DateTime::Compare(const DateTime& dt1, const DateTime& dt2)
467 DateTime::CompareTo(const DateTime& value) const
469 return DateTime::Compare(*this, value);
473 DateTime::Equals(const Object& obj) const
475 const DateTime* pOther = dynamic_cast <const DateTime*>(&obj);
481 return(*this == *pOther);
485 DateTime::GetHashCode(void) const
487 TimeSpan t = GetTime();
488 int hash = t.GetHashCode();
489 return(hash ^ (hash >> 16));
493 DateTime::GetTimeOfDay(void) const
495 long long total = ConvertDateToSeconds(&__dateTime);
498 midnight.year = __dateTime.year;
499 midnight.month = __dateTime.month;
500 midnight.day = __dateTime.day;
501 midnight.hour = MIN_HOUR;
502 midnight.minute = MIN_MINUTE;
503 midnight.second = MIN_SECOND;
505 long long since = ConvertDateToSeconds(&midnight);
507 long long span = total - since;
509 return(TimeSpan(span * 1000));
513 DateTime::GetDaysInMonth(int year, int month, int& days)
515 const static int daysInMonth[] = { 0xFF, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
517 SysTryReturn(NID_BASE, (year >= MIN_YEAR && year <= _MAX_YEAR), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
518 "[%s] The year(%d) MUST be within the %d and %d (inclusive).", GetErrorMessage(E_OUT_OF_RANGE),
519 year, MIN_YEAR, _MAX_YEAR);
520 SysTryReturn(NID_BASE, (month >= MIN_MONTH && month <= MAX_MONTH), E_OUT_OF_RANGE, E_OUT_OF_RANGE,
521 "[%s] The month(%d) MUST be within the %d and %d (inclusive).", GetErrorMessage(E_OUT_OF_RANGE),
522 month, MIN_MONTH, MAX_MONTH);
524 if (DateTime::IsLeapYear(year) && month == 2)
526 days = daysInMonth[month] + 1;
530 days = (daysInMonth[month]);
537 DateTime::Subtract(const TimeSpan& t)
539 long long total = ConvertDateToSeconds(&__dateTime);
540 long long span = total - (t.GetTicks() / 1000);
542 SysTryReturn(NID_BASE, span > 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[%s] The arguments contain invalid values.",
543 GetErrorMessage(E_OUT_OF_RANGE));
545 SysTryReturn(NID_BASE, span >= NUM_OF_SEC_IN_DAY, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
546 "[%s] The arguments contain invalid values.", GetErrorMessage(E_OUT_OF_RANGE));
548 long long maxSeconds = ConvertDateToSeconds(&(DateTime::GetMaxValue().__dateTime));
549 SysTryReturn(NID_BASE, span <= maxSeconds, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
550 "[%s] The value of the argument is outside the valid range.", GetErrorMessage(E_OUT_OF_RANGE));
552 result r = ConvertSecondsToDate(span, &__dateTime);
555 SysLogException(NID_BASE, r, "[%s] Propagating.", GetErrorMessage(r));
562 DateTime::ToString(void) const
564 wchar_t date[] = L"01/01/1970 00:00:00";
566 swprintf(date, (sizeof(date) / sizeof(wchar_t)), L"%2d/%2d/%4d %2d:%2d:%2d",
567 __dateTime.month, __dateTime.day, __dateTime.year, __dateTime.hour, __dateTime.minute,
570 if (__dateTime.month < 10)
575 if (__dateTime.day < 10)
580 if (__dateTime.year < 10)
586 else if (__dateTime.year < 100)
591 else if (__dateTime.year < 1000)
596 if (__dateTime.hour < 10)
601 if (__dateTime.minute < 10)
606 if (__dateTime.second < 10)
617 DateTime::Parse(const String& str, DateTime& dt)
619 SysTryReturn(NID_BASE,
620 (str.GetLength() == 19
621 && str[2] == L'/' && str[5] == L'/' && str[10] == L' ' && str[13] == L':' && str[16] == L':'),
622 E_INVALID_FORMAT, E_INVALID_FORMAT, ("[%s] The str(%s) is not formatted like 'mm/dd/yyyy hh:mm:ss'."),
623 GetErrorMessage(E_INVALID_FORMAT), str.GetPointer());
625 std::unique_ptr<wchar_t []> pTmp(new (std::nothrow) wchar_t [5]);
626 SysTryReturn(NID_BASE, pTmp != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
627 GetErrorMessage(E_OUT_OF_MEMORY));
629 wchar_t* pMchar = (wchar_t*) str.GetPointer();
632 wcsncpy(pTmp.get(), pMchar, 2);
635 int month = (int) wcstol(pTmp.get(), null, 10);
638 wcsncpy(pTmp.get(), pMchar + 3, 2);
641 int day = (int) wcstol(pTmp.get(), null, 10);
644 wcsncpy(pTmp.get(), pMchar + 6, 4);
647 int year = (int) wcstol(pTmp.get(), null, 10);
650 wcsncpy(pTmp.get(), pMchar + 11, 2);
653 int hour = (int) wcstol(pTmp.get(), null, 10);
656 wcsncpy(pTmp.get(), pMchar + 14, 2);
659 int minute = (int) wcstol(pTmp.get(), null, 10);
662 wcsncpy(pTmp.get(), pMchar + 17, 2);
665 int sec = (int) wcstol(pTmp.get(), null, 10);
667 // construct date time
669 result r = tmpDt.SetValue(year, month, day, hour, minute, sec);
670 SysTryReturnResult(NID_BASE, !IsFailed(r), r, ("[%s] Propagating."), GetErrorMessage(r));
678 DateTime::GetYear(void) const
680 return __dateTime.year;
684 DateTime::GetMonth(void) const
686 return __dateTime.month;
690 DateTime::GetDay(void) const
692 return __dateTime.day;
696 DateTime::GetHour(void) const
698 return __dateTime.hour;
702 DateTime::GetMinute(void) const
704 return __dateTime.minute;
708 DateTime::GetSecond(void) const
710 return __dateTime.second;
714 DateTime::GetTime(void) const
716 long long seconds = ConvertDateToSeconds(&__dateTime) - ConvertDateToSeconds(&(DateTime::GetMinValue().__dateTime));
718 return TimeSpan(seconds * 1000);
722 DateTime::GetMaxValue(void)
724 static DateTime maxValue(_MAX_YEAR, MAX_MONTH, MAX_DAY, MAX_HOUR, MAX_MINUTE, MAX_SECOND);
730 DateTime::GetMinValue(void)
732 static DateTime minValue(MIN_YEAR, MIN_MONTH, MIN_DAY, MIN_HOUR, MIN_MINUTE, MIN_SECOND);
738 DateTime::IsLeapYear(void) const
740 return DateTime::IsLeapYear(__dateTime.year);
744 DateTime::IsLeapYear(int year)
746 return year >= 0 && (!(year % 4) && ((year % 100) || !(year % 400)));
749 DateTime::DateTime(int year, int month, int day, int hour, int minute, int second)
750 : __pDateTimeImpl(null)
752 SetValue(year, month, day, hour, minute, second);
756 DateTime::ConvertSecondsToDate(long long seconds, TmDateTime* pDateTime)
769 bool leapYear = false;
771 totalDays = (int) (seconds / SEC_IN_A_DAY);
773 // Get a year and leapYear
774 year = CountYears(totalDays);
775 SysTryReturn(NID_BASE, year >= MIN_YEAR && year <= _MAX_YEAR, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
776 "[%s] The arguments (%d) contain invalid values.", GetErrorMessage(E_OUT_OF_RANGE), seconds);
779 leapYear = DateTime::IsLeapYear(year);
781 // Get days without year;
782 tempDays = totalDays - CountDays(year);
784 // Check the boundary of days
803 if (tempDays == 0) // month = 0 , day = 0
805 dt.__dateTime.year = year;
806 dt.__dateTime.month = 0;
807 dt.__dateTime.day = 0;
808 dt.__dateTime.hour = 0;
809 dt.__dateTime.minute = 0;
810 dt.__dateTime.second = 0;
812 tempSeconds = (int) (seconds - ConvertDateToSeconds(&(dt.__dateTime)));
815 hour = tempSeconds / NUM_OF_SEC_IN_HOUR;
817 tempSeconds -= hour * NUM_OF_SEC_IN_HOUR;
820 minute = tempSeconds / NUM_OF_SEC_IN_MINUTE;
823 second = tempSeconds - minute * NUM_OF_SEC_IN_MINUTE;
825 SetValue(year, 1, 1, hour, minute, second);
831 int leapYearDaysCount = 0;
833 for (; leapYearDaysCount < 12; leapYearDaysCount++)
835 if ((DAYS_IN_LEAP_YEAR[leapYearDaysCount] < tempDays) && (tempDays <= DAYS_IN_LEAP_YEAR[leapYearDaysCount + 1]))
837 month = leapYearDaysCount + 1;
842 SysTryReturn(NID_BASE, leapYearDaysCount != 12, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
843 "[%s] The arguments (%d) contain invalid values.", GetErrorMessage(E_OUT_OF_RANGE), seconds);
845 day = tempDays - DAYS_IN_LEAP_YEAR[month - 1];
851 for (; daysCount < 12; daysCount++)
853 if ((DAYS[daysCount] < tempDays) && (tempDays <= DAYS[daysCount + 1]))
855 month = daysCount + 1;
860 SysTryReturn(NID_BASE, daysCount != 12, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
861 "[%s] The arguments (%d) contain invalid values.", GetErrorMessage(E_OUT_OF_RANGE), seconds);
864 day = tempDays - DAYS[month - 1];
867 dt.SetValue(year, month, day, 0, 0, 0);
870 tempSeconds = (int) (seconds - ConvertDateToSeconds(&(dt.__dateTime)));
871 hour = tempSeconds / NUM_OF_SEC_IN_HOUR;
874 tempSeconds -= hour * NUM_OF_SEC_IN_HOUR;
875 minute = tempSeconds / NUM_OF_SEC_IN_MINUTE;
878 second = tempSeconds - minute * NUM_OF_SEC_IN_MINUTE;
880 SetValue(year, month, day, hour, minute, second);
886 DateTime::ConvertDateToSeconds(const TmDateTime* pDateTime) const
889 long long seconds = 0;
892 days = CountDays(pDateTime->year);
895 if (pDateTime->month != 0)
897 if (DateTime::IsLeapYear(pDateTime->year))
899 days += DAYS_IN_LEAP_YEAR[pDateTime->month - 1];
903 days += DAYS[pDateTime->month - 1];
908 days += pDateTime->day;
910 // Convert to Seconds
911 seconds = days * NUM_OF_SEC_IN_DAY;
914 seconds += pDateTime->hour * NUM_OF_SEC_IN_HOUR;
917 seconds += pDateTime->minute * NUM_OF_SEC_IN_MINUTE;
920 seconds += pDateTime->second;