2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file FLclGregorianCalendar.cpp
19 * @brief This is the implementation file for GregorianCalendar class.
22 #include <unique_ptr.h>
24 #include <FBaseDateTime.h>
25 #include <FBaseSysLog.h>
26 #include <FLclGregorianCalendar.h>
27 #include "FLcl_CalendarImpl.h"
28 #include "FLcl_LocaleManagerImpl.h"
30 using namespace Tizen::Base;
32 namespace Tizen { namespace Locales
35 //////////////////////////////////////////////////////////////////////////////////
37 const int GregorianCalendar::MONTH_LENGTH[24] =
39 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, // Days in month in normal year
40 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // Days in month in leap year
43 // Set cumulative number of days at first day of month
44 const int GregorianCalendar::NUM_DAYS[24] =
46 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, // Cumulative number of days at first day of month in normal year
47 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 // Cumulative number of days at first day of month in leap year
50 GregorianCalendar::GregorianCalendar(void)
51 : __normalizedGregorianCutover(DEFAULT_GREGORIAN_CUTOVER)
52 , __gregorianCutoverYear(1582)
53 , __cutoverJulianDay(GregorianCalendar::CUTOVER_JULIAN_DAY)
54 , __pGregorianCalendarImpl(null)
58 GregorianCalendar::~GregorianCalendar(void)
60 delete _pCalendarImpl;
61 _pCalendarImpl = null;
64 // This method is copy constructor
66 GregorianCalendar::Construct(const GregorianCalendar& gc)
68 // Object is not allowed to construct twice
69 SysAssertf(_pCalendarImpl == null,
70 "Already constructed! Calling Construct() twice or more on a same instance is not allowed for this class");
72 if (gc._pCalendarImpl != null)
74 std::unique_ptr< Calendar > pCalendar(gc._pCalendarImpl->CloneN());
75 SysTryReturnResult(NID_LCL, pCalendar != null, E_OUT_OF_MEMORY, "Memory allocation failed");
77 _pCalendarImpl = dynamic_cast< _CalendarImpl* >(pCalendar.get());
78 if (_pCalendarImpl != null)
82 __cutoverJulianDay = gc.__cutoverJulianDay;
83 __normalizedGregorianCutover = gc.__normalizedGregorianCutover;
84 __gregorianCutoverYear = gc.__gregorianCutoverYear;
92 GregorianCalendar::Construct(void)
94 return Construct(TimeZone::GetGmtTimeZone(), _LocaleManagerImpl::GetSystemLocale());
98 GregorianCalendar::Construct(const TimeZone& timezone)
100 return Construct(timezone, _LocaleManagerImpl::GetSystemLocale());
104 GregorianCalendar::Construct(const Locale& locale)
106 return Construct(TimeZone::GetGmtTimeZone(), locale);
110 GregorianCalendar::Construct(const TimeZone& timezone, const Locale& locale)
112 // Object is not allowed to construct twice
113 SysAssertf(_pCalendarImpl == null,
114 "Already constructed! Calling Construct() twice or more on a same instance is not allowed for this class");
116 std::unique_ptr< _CalendarImpl > pCalendarImpl(new (std::nothrow) _CalendarImpl);
117 SysTryReturnResult(NID_LCL, pCalendarImpl != null, E_OUT_OF_MEMORY, "Memory allocation failed");
119 result r = pCalendarImpl->Construct(timezone, locale);
122 _pCalendarImpl = pCalendarImpl.release();
124 SetGregorianChange(GetGregorianChange());
132 GregorianCalendar::Construct(int year, int month, int day, int hourOfDay, int minute, int second)
134 result r = Construct(TimeZone::GetGmtTimeZone(), _LocaleManagerImpl::GetSystemLocale());
137 r = SetTime(year, month, day, hourOfDay, minute, second);
143 GregorianCalendar::Construct(const DateTime& dateTime)
145 return Construct(dateTime.GetYear(),
149 dateTime.GetMinute(),
150 dateTime.GetSecond());
154 GregorianCalendar::AddTimeField(TimeField field, int amount)
156 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
157 return _pCalendarImpl->AddTimeField(field, amount);
161 GregorianCalendar::DayToFields(int day, int& year, int& month, int& dayOfMonth, int& dayOfWeek, int& dayOfYear)
163 _CalendarImpl calImpl;
164 result r = calImpl.Construct();
167 r = calImpl.SetJulianDay(day + GregorianCalendar::EPOCH_START_AS_JULIAN_DAY);
170 year = calImpl.GetTimeField(TIME_FIELD_YEAR);
171 month = calImpl.GetTimeField(TIME_FIELD_MONTH);
172 dayOfMonth = calImpl.GetTimeField(TIME_FIELD_DAY_OF_MONTH);
173 dayOfWeek = calImpl.GetTimeField(TIME_FIELD_DAY_OF_WEEK);
174 dayOfYear = calImpl.GetTimeField(TIME_FIELD_DAY_OF_YEAR);
179 // This method gets the actual minimum value that a given field could have.
180 // For Gregorian calendar, it is the same as GetMinTimeField() and GetGreatestMinimum()
182 GregorianCalendar::GetActualMinTimeField(TimeField field) const
184 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
185 return _pCalendarImpl->GetActualMinTimeField(field);
189 // This method gets the actual maximum value that this field could have, given the current date.
190 // This method has a limitation (also GetActualMinimum). It will not behave properly at the extreme limits of Gregorian calendar's
191 // representable range.
192 // For calendars with the default Gregorian cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
193 // Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT zones.
194 // As a result, if the calendar is set to Aug 1 292278994 AD, the actual maximum of DAY_OF_MONTH is 17, not 30.
197 GregorianCalendar::GetActualMaxTimeField(TimeField field) const
199 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
200 return _pCalendarImpl->GetActualMaxTimeField(field);
203 //This method returns the Gregorian cutover.
205 GregorianCalendar::GetGregorianChange(void) const
207 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
208 return _pCalendarImpl->GetGregorianChange();
212 GregorianCalendar::GetType(void) const
214 return CALENDAR_GREGORIAN;
218 GregorianCalendar::IsInDst(bool& isInDst) const
220 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
221 return _pCalendarImpl->IsInDst(isInDst);
225 GregorianCalendar::IsLeapYear(int year) const
227 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
228 return _pCalendarImpl->IsLeapYear(year);
232 GregorianCalendar::Roll(TimeField field, int amount)
234 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
235 return _pCalendarImpl->Roll(field, amount);
239 GregorianCalendar::SetGregorianChange(long long change)
241 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
243 result r = E_SUCCESS;
244 if (_pCalendarImpl->GetGregorianChange() != change)
246 r = _pCalendarImpl->SetGregorianChange(change);
249 std::unique_ptr< Calendar > pCalendar(_pCalendarImpl->CloneN());
250 SysTryReturnResult(NID_LCL, pCalendar != null, E_OUT_OF_MEMORY, "Memory allocation failed");
252 _CalendarImpl* pCalImpl = dynamic_cast< _CalendarImpl* >(pCalendar.get());
253 if (pCalImpl != null)
255 pCalImpl->SetTimeInMillisec(change);
257 __cutoverJulianDay = pCalImpl->GetJulianDay();
258 // __normalizedGregorianCutover = change * Calendar::ONE_DAY_IN_MILLISEC;
260 __gregorianCutoverYear = pCalImpl->GetTimeField(TIME_FIELD_YEAR);
261 if (pCalImpl->GetTimeField(TIME_FIELD_ERA) == GREGORIAN_CALENDAR_BC)
263 __gregorianCutoverYear = 1 - __gregorianCutoverYear; // update __gregorianCutoverYear for BC, 0 based
266 long long julianDayFromEpoch = __cutoverJulianDay - GregorianCalendar::EPOCH_START_AS_JULIAN_DAY;
267 __normalizedGregorianCutover = julianDayFromEpoch * Calendar::ONE_DAY_IN_MILLISEC;
269 // Handle the rare case of numeric overflow
270 if (julianDayFromEpoch < 0 && __normalizedGregorianCutover > 0)
272 __normalizedGregorianCutover = (julianDayFromEpoch + 1) * Calendar::ONE_DAY_IN_MILLISEC;
280 GregorianCalendar::IsGregorian(void) const
286 GregorianCalendar::GetNormalizedGregorianCutover(void) const
288 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
289 return __normalizedGregorianCutover;
293 GregorianCalendar::GetGregorianCutoverYear(void) const
295 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
296 return __gregorianCutoverYear;
300 GregorianCalendar::GetCutoverJulianDay(void) const
302 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
303 return __cutoverJulianDay;
307 GregorianCalendar::GetTimeInMillisecFromEpoch(long long& millisec) const
309 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
310 result r = _pCalendarImpl->GetTimeInMillisec(millisec);
313 millisec -= GregorianCalendar::EPOCH_OFFSET_IN_MILLISEC;
319 GregorianCalendar::SetTimeInMillisecFromEpoch(long long millisec)
321 SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
323 millisec += GregorianCalendar::EPOCH_OFFSET_IN_MILLISEC;
324 return _pCalendarImpl->SetTimeInMillisec(millisec);
327 // added for backward compatibility
329 GregorianCalendar::RollWithSingleUnit(TimeField field, bool up)
331 return E_UNSUPPORTED_OPERATION;
334 // added for backward compatibility
336 GregorianCalendar::ComputeTimeFields(void)
338 return E_UNSUPPORTED_OPERATION;
341 // added for backward compatibility
343 GregorianCalendar::ComputeTime(void)
345 return E_UNSUPPORTED_OPERATION;
348 // added for backward compatibility
350 GregorianCalendar::GetMonthLength(int extendedYear, int month) const
352 SetLastResult(E_UNSUPPORTED_OPERATION);
356 // added for backward compatibility
358 GregorianCalendar::HandleGetLimit(TimeField field, CalendarLimitType limitType) const
360 SetLastResult(E_UNSUPPORTED_OPERATION);
364 // added for backward compatibility
366 GregorianCalendar::CloneN(void) const
368 SetLastResult(E_UNSUPPORTED_OPERATION);