Modified an api call flow
[platform/framework/native/appfw.git] / src / locales / FLclGregorianCalendar.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17
18 /**
19 * @file         FLclGregorianCalendar.cpp
20 * @brief        This is the implementation file for GregorianCalendar class.
21 */
22
23 #include <unique_ptr.h>
24
25 #include <FBaseDateTime.h>
26 #include <FBaseSysLog.h>
27 #include <FLclGregorianCalendar.h>
28 #include "FLcl_CalendarImpl.h"
29 #include "FLcl_LocaleManagerImpl.h"
30
31 using namespace Tizen::Base;
32
33 namespace Tizen { namespace Locales
34 {
35
36 //////////////////////////////////////////////////////////////////////////////////
37 // Set monthLength[]
38 const int GregorianCalendar::MONTH_LENGTH[24] =
39 {
40         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,                             // Days in month in normal year
41         31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31                              // Days in month in leap year
42 };
43
44 // Set cumulative number of days at first day of month
45 const int GregorianCalendar::NUM_DAYS[24] =
46 {
47         0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,       // Cumulative number of days at first day of month in normal year
48         0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335        // Cumulative number of days at first day of month in leap year
49 };
50
51 GregorianCalendar::GregorianCalendar(void)
52         : __normalizedGregorianCutover(DEFAULT_GREGORIAN_CUTOVER)
53         , __gregorianCutoverYear(1582)
54         , __cutoverJulianDay(GregorianCalendar::CUTOVER_JULIAN_DAY)
55         , __pGregorianCalendarImpl(null)
56 {
57 }
58
59 GregorianCalendar::~GregorianCalendar(void)
60 {
61         delete _pCalendarImpl;
62         _pCalendarImpl = null;
63 }
64
65 // This method is copy constructor
66 result
67 GregorianCalendar::Construct(const GregorianCalendar& gc)
68 {
69         // Object is not allowed to construct twice
70         SysAssertf(_pCalendarImpl == null,
71                 "Already constructed! Calling Construct() twice or more on a same instance is not allowed for this class");
72
73         if (gc._pCalendarImpl != null)
74         {
75                 std::unique_ptr< Calendar > pCalendar(gc._pCalendarImpl->CloneN());
76                 SysTryReturnResult(NID_LCL, pCalendar != null, E_OUT_OF_MEMORY, "Memory allocation failed");
77
78                 _pCalendarImpl = dynamic_cast< _CalendarImpl* >(pCalendar.get());
79                 if (_pCalendarImpl != null)
80                 {
81                         pCalendar.release();
82
83                         __cutoverJulianDay = gc.__cutoverJulianDay;
84                         __normalizedGregorianCutover = gc.__normalizedGregorianCutover;
85                         __gregorianCutoverYear = gc.__gregorianCutoverYear;
86                 }
87         }
88
89         return E_SUCCESS;
90 }
91
92 result
93 GregorianCalendar::Construct(void)
94 {
95         return Construct(TimeZone::GetGmtTimeZone(), _LocaleManagerImpl::GetSystemLocale());
96 }
97
98 result
99 GregorianCalendar::Construct(const TimeZone& timezone)
100 {
101         return Construct(timezone, _LocaleManagerImpl::GetSystemLocale());
102 }
103
104 result
105 GregorianCalendar::Construct(const Locale& locale)
106 {
107         return Construct(TimeZone::GetGmtTimeZone(), locale);
108 }
109
110 result
111 GregorianCalendar::Construct(const TimeZone& timezone, const Locale& locale)
112 {
113         // Object is not allowed to construct twice
114         SysAssertf(_pCalendarImpl == null,
115                 "Already constructed! Calling Construct() twice or more on a same instance is not allowed for this class");
116
117         std::unique_ptr< _CalendarImpl > pCalendarImpl(new (std::nothrow) _CalendarImpl);
118         SysTryReturnResult(NID_LCL, pCalendarImpl != null, E_OUT_OF_MEMORY, "Memory allocation failed");
119
120         result r = pCalendarImpl->Construct(timezone, locale);
121         if (!IsFailed(r))
122         {
123                 _pCalendarImpl = pCalendarImpl.release();
124
125                 SetGregorianChange(GetGregorianChange());
126                 return E_SUCCESS;
127         }
128
129         return r;
130 }
131
132 result
133 GregorianCalendar::Construct(int year, int month, int day, int hourOfDay, int minute, int second)
134 {
135         result r = Construct(TimeZone::GetGmtTimeZone(), _LocaleManagerImpl::GetSystemLocale());
136         if (!IsFailed(r))
137         {
138                 r = SetTime(year, month, day, hourOfDay, minute, second);
139         }
140         return r;
141 }
142
143 result
144 GregorianCalendar::Construct(const DateTime& dateTime)
145 {
146         return Construct(dateTime.GetYear(),
147                                          dateTime.GetMonth(),
148                                          dateTime.GetDay(),
149                                          dateTime.GetHour(),
150                                          dateTime.GetMinute(),
151                                          dateTime.GetSecond());
152 }
153
154 result
155 GregorianCalendar::AddTimeField(TimeField field, int amount)
156 {
157         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
158         return _pCalendarImpl->AddTimeField(field, amount);
159 }
160
161 void
162 GregorianCalendar::DayToFields(int day, int& year, int& month, int& dayOfMonth, int& dayOfWeek, int& dayOfYear)
163 {
164         _CalendarImpl calImpl;
165         result r = calImpl.Construct();
166         if (!IsFailed(r))
167         {
168                 r = calImpl.SetJulianDay(day + GregorianCalendar::EPOCH_START_AS_JULIAN_DAY);
169                 if (!IsFailed(r))
170                 {
171                         year = calImpl.GetTimeField(TIME_FIELD_YEAR);
172                         month = calImpl.GetTimeField(TIME_FIELD_MONTH);
173                         dayOfMonth = calImpl.GetTimeField(TIME_FIELD_DAY_OF_MONTH);
174                         dayOfWeek = calImpl.GetTimeField(TIME_FIELD_DAY_OF_WEEK);
175                         dayOfYear = calImpl.GetTimeField(TIME_FIELD_DAY_OF_YEAR);
176                 }
177         }
178 }
179
180 // This method gets the actual minimum value that a given field could have.
181 // For Gregorian calendar, it is the same as GetMinTimeField() and GetGreatestMinimum()
182 int
183 GregorianCalendar::GetActualMinTimeField(TimeField field) const
184 {
185         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
186         return _pCalendarImpl->GetActualMinTimeField(field);
187 }
188
189 //
190 // This method gets the actual maximum value that this field could have, given the current date.
191 // This method has a limitation (also GetActualMinimum). It will not behave properly at the extreme limits of Gregorian calendar's
192 // representable range.
193 // For calendars with the default Gregorian cutover, these limits are Sun Dec 02 16:47:04 GMT 292269055 BC to Sun
194 // Aug 17 07:12:55 GMT 292278994 AD, somewhat different for non-GMT zones.
195 // As a result, if the calendar is set to Aug 1 292278994 AD, the actual maximum of DAY_OF_MONTH is 17, not 30.
196 //
197 int
198 GregorianCalendar::GetActualMaxTimeField(TimeField field) const
199 {
200         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
201         return _pCalendarImpl->GetActualMaxTimeField(field);
202 }
203
204 //This method returns the Gregorian cutover.
205 long long
206 GregorianCalendar::GetGregorianChange(void) const
207 {
208         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
209         return _pCalendarImpl->GetGregorianChange();
210 }
211
212 CalendarType
213 GregorianCalendar::GetType(void) const
214 {
215         return CALENDAR_GREGORIAN;
216 }
217
218 result
219 GregorianCalendar::IsInDst(bool& isInDst) const
220 {
221         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
222         return _pCalendarImpl->IsInDst(isInDst);
223 }
224
225 bool
226 GregorianCalendar::IsLeapYear(int year) const
227 {
228         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
229         return _pCalendarImpl->IsLeapYear(year);
230 }
231
232 result
233 GregorianCalendar::Roll(TimeField field, int amount)
234 {
235         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
236         return _pCalendarImpl->Roll(field, amount);
237 }
238
239 result
240 GregorianCalendar::SetGregorianChange(long long change)
241 {
242         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
243
244         result r = E_SUCCESS;
245         if (_pCalendarImpl->GetGregorianChange() != change)
246         {
247                 r = _pCalendarImpl->SetGregorianChange(change);
248         }
249
250         std::unique_ptr< Calendar > pCalendar(_pCalendarImpl->CloneN());
251         SysTryReturnResult(NID_LCL, pCalendar != null, E_OUT_OF_MEMORY, "Memory allocation failed");
252
253         _CalendarImpl* pCalImpl = dynamic_cast< _CalendarImpl* >(pCalendar.get());
254         if (pCalImpl != null)
255         {
256                 pCalImpl->SetTimeInMillisec(change);
257
258                 __cutoverJulianDay = pCalImpl->GetJulianDay();
259                 //        __normalizedGregorianCutover = change * Calendar::ONE_DAY_IN_MILLISEC;
260
261                 __gregorianCutoverYear = pCalImpl->GetTimeField(TIME_FIELD_YEAR);
262                 if (pCalImpl->GetTimeField(TIME_FIELD_ERA) == GREGORIAN_CALENDAR_BC)
263                 {
264                         __gregorianCutoverYear = 1 - __gregorianCutoverYear;                    // update __gregorianCutoverYear for BC, 0 based
265                 }
266
267                 long long julianDayFromEpoch = __cutoverJulianDay - GregorianCalendar::EPOCH_START_AS_JULIAN_DAY;
268                 __normalizedGregorianCutover = julianDayFromEpoch * Calendar::ONE_DAY_IN_MILLISEC;
269
270                 // Handle the rare case of numeric overflow
271                 if (julianDayFromEpoch < 0 && __normalizedGregorianCutover > 0)
272                 {
273                         __normalizedGregorianCutover = (julianDayFromEpoch + 1) * Calendar::ONE_DAY_IN_MILLISEC;
274                 }
275         }
276
277         return r;
278 }
279
280 bool
281 GregorianCalendar::IsGregorian(void) const
282 {
283         return true;
284 }
285
286 long long
287 GregorianCalendar::GetNormalizedGregorianCutover(void) const
288 {
289         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
290         return __normalizedGregorianCutover;
291 }
292
293 int
294 GregorianCalendar::GetGregorianCutoverYear(void) const
295 {
296         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
297         return __gregorianCutoverYear;
298 }
299
300 int
301 GregorianCalendar::GetCutoverJulianDay(void) const
302 {
303         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
304         return __cutoverJulianDay;
305 }
306
307 result
308 GregorianCalendar::GetTimeInMillisecFromEpoch(long long& millisec) const
309 {
310         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
311         result r = _pCalendarImpl->GetTimeInMillisec(millisec);
312         if (!IsFailed(r))
313         {
314                 millisec -= GregorianCalendar::EPOCH_OFFSET_IN_MILLISEC;
315         }
316         return r;
317 }
318
319 result
320 GregorianCalendar::SetTimeInMillisecFromEpoch(long long millisec)
321 {
322         SysAssertf(_pCalendarImpl != null, "Not yet constructed! Construct() should be called before use.");
323
324         millisec += GregorianCalendar::EPOCH_OFFSET_IN_MILLISEC;
325         return _pCalendarImpl->SetTimeInMillisec(millisec);
326 }
327
328 // added for backward compatibility
329 result
330 GregorianCalendar::RollWithSingleUnit(TimeField field, bool up)
331 {
332         return E_UNSUPPORTED_OPERATION;
333 }
334
335 // added for backward compatibility
336 result
337 GregorianCalendar::ComputeTimeFields(void)
338 {
339         return E_UNSUPPORTED_OPERATION;
340 }
341
342 // added for backward compatibility
343 result
344 GregorianCalendar::ComputeTime(void)
345 {
346         return E_UNSUPPORTED_OPERATION;
347 }
348
349 // added for backward compatibility
350 int
351 GregorianCalendar::GetMonthLength(int extendedYear, int month) const
352 {
353         SetLastResult(E_UNSUPPORTED_OPERATION);
354         return -1;
355 }
356
357 // added for backward compatibility
358 int
359 GregorianCalendar::HandleGetLimit(TimeField field, CalendarLimitType limitType) const
360 {
361         SetLastResult(E_UNSUPPORTED_OPERATION);
362         return -1;
363 }
364
365 // added for backward compatibility
366 Calendar*
367 GregorianCalendar::CloneN(void) const
368 {
369         SetLastResult(E_UNSUPPORTED_OPERATION);
370         return null;
371 }
372
373
374 };
375 };      // Tizen::Locales