Fix memory leaks
[platform/framework/native/appfw.git] / src / locales / FLcl_TimeZoneImpl.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            FLcl_TimeZoneImpl.cpp
19  * @brief           This is the implementation file for _TimeZoneImpl class.
20  */
21
22 #include <unique_ptr.h>
23
24 #include <FBaseSysLog.h>
25 #include <FLclTimeZone.h>
26
27 #include "FLcl_LocaleData.h"
28 #include "FLcl_TimeZoneImpl.h"
29
30 using namespace Tizen::Base;
31
32 namespace Tizen { namespace Locales
33 {
34
35 _TimeZoneImpl::_TimeZoneImpl(void)
36         : __icuTimeZone(0, "")
37         , __dstStartingYear(0)
38         , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
39         , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
40 {
41
42 }
43
44 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id)
45         : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
46         , __dstStartingYear(0)
47         , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
48         , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
49 {
50
51 }
52
53 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id, const TimeRule& startRule, const TimeRule& endRule, int dstOffset)
54         : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
55         , __dstStartingYear(0)
56         , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
57         , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
58 {
59         SetDstRules(startRule, endRule, dstOffset);
60 }
61
62 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
63         : __icuTimeZone(otherTimeZone.__icuTimeZone)
64         , __dstStartingYear(otherTimeZone.__dstStartingYear)
65         , __startingRule(otherTimeZone.__startingRule)
66         , __endingRule(otherTimeZone.__endingRule)
67 {
68 }
69
70 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone)
71         : __icuTimeZone(0, "")
72         , __dstStartingYear(0)
73         , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
74         , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
75 {
76         U_ICU_NAMESPACE::UnicodeString id;
77         __icuTimeZone.setID(icuTimeZone.getID(id));
78         __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
79 }
80
81 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone, UDate icuDate)
82         : __icuTimeZone(0, "")
83         , __dstStartingYear(0)
84         , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
85         , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
86 {
87         U_ICU_NAMESPACE::UnicodeString id;
88         __icuTimeZone.setID(icuTimeZone.getID(id));
89         __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
90
91         U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(&icuTimeZone);
92         if (pIcuTz)
93         {
94                 TimeRule startingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
95                 TimeRule endingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
96
97                 int dstSaving = 0;
98                 UErrorCode status = U_ZERO_ERROR;
99                 U_ICU_NAMESPACE::InitialTimeZoneRule* pInitial = null;
100                 U_ICU_NAMESPACE::AnnualTimeZoneRule* pStd = null;
101                 U_ICU_NAMESPACE::AnnualTimeZoneRule* pDst = null;
102                 pIcuTz->getSimpleRulesNear(icuDate, pInitial, pStd, pDst, status);
103                 if (pStd && pDst)
104                 {
105                         result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), startingRule);
106                         if (r == E_SUCCESS)
107                         {
108                                 dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
109                                 GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), endingRule);
110                         }
111
112                         int dstStartingYear = pDst->getStartYear();
113                         SetDstStartingYear(dstStartingYear);
114                 }
115
116                 delete pInitial;
117                 delete pStd;
118                 delete pDst;
119                 SetDstRules(startingRule, endingRule, dstSaving);
120         }
121 }
122
123 _TimeZoneImpl*
124 _TimeZoneImpl::CloneN(void)
125 {
126         return new (std::nothrow) _TimeZoneImpl(*this);
127 }
128
129 _TimeZoneImpl&
130 _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
131 {
132         if (*this != otherTimeZone)
133         {
134                 __icuTimeZone = otherTimeZone.__icuTimeZone;
135                 __dstStartingYear = otherTimeZone.__dstStartingYear;
136                 __startingRule = otherTimeZone.__startingRule;
137                 __endingRule = otherTimeZone.__endingRule;
138         }
139         return *this;
140 }
141
142 _TimeZoneImpl::~_TimeZoneImpl(void)
143 {
144
145 }
146
147 U_ICU_NAMESPACE::SimpleTimeZone
148 _TimeZoneImpl::GetIcuTimeZone(void) const
149 {
150         return __icuTimeZone;
151 }
152
153
154 bool
155 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
156 {
157         return __icuTimeZone == otherTimeZone.__icuTimeZone;
158 }
159
160 bool
161 _TimeZoneImpl::operator !=(const _TimeZoneImpl& otherTimeZone) const
162 {
163         return !(*this == otherTimeZone);
164 }
165
166 bool
167 _TimeZoneImpl::Equals(const Object& obj) const
168 {
169         const _TimeZoneImpl* pTimeZoneImpl = dynamic_cast<const _TimeZoneImpl*>(&obj);
170         if (pTimeZoneImpl)
171         {
172                 return (*this == *pTimeZoneImpl);
173         }
174         return false;
175 }
176
177 int
178 _TimeZoneImpl::GetHashCode(void) const
179 {
180         int hashCode = GetId().GetHashCode();
181         Integer intValues = GetRawOffset() + GetDstSavings() + GetDstStartingYear() + IsDstUsed();
182         hashCode = (hashCode << 5) - hashCode + intValues.GetHashCode();
183         hashCode = (hashCode << 5) - hashCode + __startingRule.GetHashCode();
184         hashCode = (hashCode << 5) - hashCode + __endingRule.GetHashCode();
185
186         return hashCode;
187 }
188
189 String
190 _TimeZoneImpl::GetId(void) const
191 {
192         U_ICU_NAMESPACE::UnicodeString icuStr;
193         return _LocaleData::GetOspString(__icuTimeZone.getID(icuStr));
194 }
195
196 void
197 _TimeZoneImpl::SetId(const String& id)
198 {
199         U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
200         __icuTimeZone.setID(icuStr);
201 }
202
203 int
204 _TimeZoneImpl::GetRawOffset(void) const
205 {
206         return __icuTimeZone.getRawOffset() / ONE_MIN_IN_MILLISEC;
207 }
208
209 void
210 _TimeZoneImpl::SetRawOffset(int rawOffset)
211 {
212         __icuTimeZone.setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
213 }
214
215 int
216 _TimeZoneImpl::GetDstStartingYear(void) const
217 {
218         return __dstStartingYear;
219 }
220
221 void
222 _TimeZoneImpl::SetDstStartingYear(int year)
223 {
224         __dstStartingYear = year;
225         __icuTimeZone.setStartYear(year);
226 }
227
228 int
229 _TimeZoneImpl::GetDstSavings(void) const
230 {
231         return __icuTimeZone.getDSTSavings() / ONE_MIN_IN_MILLISEC;
232 }
233
234 void
235 _TimeZoneImpl::SetDstSavings(int dstSavings)
236 {
237         UErrorCode ec = U_ZERO_ERROR;
238         __icuTimeZone.setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
239 }
240
241 const TimeRule*
242 _TimeZoneImpl::GetDstStartingRule(void) const
243 {
244         return __startingRule.GetMonth() != MONTH_UNDEFINED ? &__startingRule : null;
245 }
246
247 void
248 _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
249 {
250         int month = 0;
251         int dayOfWeekInMonth = 0;
252         int dayOfWeek = 0;
253         int time = 0;
254         int mode = 0;
255
256         UErrorCode ec = U_ZERO_ERROR;
257         GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
258
259         U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
260         __icuTimeZone.setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
261         __startingRule = startRule;
262 }
263
264 const TimeRule*
265 _TimeZoneImpl::GetDstEndingRule(void) const
266 {
267         return __endingRule.GetMonth() != MONTH_UNDEFINED ? &__endingRule : null;
268 }
269
270 void
271 _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
272 {
273         int month = 0;
274         int dayOfWeekInMonth = 0;
275         int dayOfWeek = 0;
276         int time = 0;
277         int mode = 0;
278
279         UErrorCode ec = U_ZERO_ERROR;
280         GetIcuTimeRuleValue(endRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
281
282         U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
283         __icuTimeZone.setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
284         __endingRule = endRule;
285 }
286
287 result
288 _TimeZoneImpl::SetDstRules(const TimeRule& startRule, const TimeRule& endRule, int dstSavings)
289 {
290         SysTryReturnResult(NID_LCL, dstSavings >= 0,
291                         E_OUT_OF_RANGE, "dstSavings [%d] should be greater or equal to than 0", dstSavings);
292         SysTryReturnResult(NID_LCL, dstSavings < ONE_DAY_IN_MINUTE,
293                         E_OUT_OF_RANGE, "dstSavings [%d] should be greater than %d", dstSavings, ONE_DAY_IN_MINUTE);
294         SetDstStartingRule(startRule);
295         SetDstEndingRule(endRule);
296         SetDstSavings(dstSavings);
297         return E_SUCCESS;
298 }
299
300 result
301 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
302 {
303         UErrorCode ec = U_ZERO_ERROR;
304         __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
305         rawOffset /= ONE_MIN_IN_MILLISEC;
306         dstOffset /= ONE_MIN_IN_MILLISEC;
307         return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
308 }
309
310 result
311 _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
312 {
313         TimeSpan ts(ticks);
314         DateTime date;
315         date.SetValue(ts.GetTicks());
316
317         int rawOffset = 0;
318         int dstOffset = 0;
319         UErrorCode ec = U_ZERO_ERROR;
320         __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
321         offset = (rawOffset + dstOffset) / ONE_MIN_IN_MILLISEC;
322         return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
323 }
324
325 bool
326 _TimeZoneImpl::IsDstUsed(void) const
327 {
328         return __icuTimeZone.useDaylightTime();
329 }
330
331 const _TimeZoneImpl*
332 _TimeZoneImpl::GetTimeZoneImpl(const TimeZone& ospTimeZone)
333 {
334         return ospTimeZone.__pTimeZoneImpl;
335 }
336
337 result
338 _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
339 {
340         U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
341         std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
342         SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
343
344         U_ICU_NAMESPACE::UnicodeString retIcuStr;
345         SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
346                                 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
347
348         U_ICU_NAMESPACE::SimpleTimeZone icuTimeZone(pIcuTimeZone->getRawOffset(), icuStr);
349         std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(icuTimeZone));
350         if (pTimeZoneImpl)
351         {
352                 delete timeZone.__pTimeZoneImpl;
353                 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
354                 return E_SUCCESS;
355         }
356
357         return E_INVALID_ARG;
358 }
359
360 result
361 _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Locales::TimeZone& timeZone)
362 {
363         U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
364         std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
365         SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
366
367         U_ICU_NAMESPACE::UnicodeString retIcuStr;
368         SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
369                                 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
370
371         std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(*pIcuTimeZone, _LocaleData::GetIcuDate(utcTime)));
372         if (pTimeZoneImpl)
373         {
374                 delete timeZone.__pTimeZoneImpl;
375                 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
376                 return E_SUCCESS;
377         }
378
379         return E_INVALID_ARG;
380 }
381
382 void
383 _TimeZoneImpl::GetIcuTimeRuleValue(const TimeRule& ospRule, int& month, int& dayOfWeekInMonth, int& dayOfWeek, int& time, int& mode)
384 {
385         if (ospRule.GetMonth() != MONTH_UNDEFINED)
386         {
387                 month = ospRule.GetMonth() - 1;
388
389                 int ospDay = ospRule.GetDay();
390                 dayOfWeekInMonth = (ospDay == TimeRule::DAY_UNDEFINED)? 0 : ospDay;
391
392                 int ospDayOfWeek =  ospRule.GetDayOfWeek();
393                 dayOfWeek = (ospDayOfWeek == WEEK_UNDEFINED)? 0 : ospDayOfWeek;
394
395                 time = ospRule.GetHour() * ONE_HOUR_IN_MILLISEC + ospRule.GetMinute() * ONE_MIN_IN_MILLISEC;
396
397                 int ospTimeMode = ospRule.GetTimeMode();
398                 mode = IcuDateTimeRule::WALL_TIME;
399                 if (ospTimeMode == Tizen::System::TIME_MODE_UTC)
400                 {
401                         mode = IcuDateTimeRule::UTC_TIME;
402                 }
403
404                 if (ospTimeMode == Tizen::System::TIME_MODE_STANDARD)
405                 {
406                         mode = IcuDateTimeRule::STANDARD_TIME;
407                 }
408
409                 switch (ospRule.GetRuleMode())
410                 {
411                 case EXACT_DAY:
412                 case BACKWARD_FROM_END_OF_MONTH:
413                         dayOfWeek = 0;
414                         break;
415                 case DAY_OF_WEEK_IN_MONTH:
416                         dayOfWeekInMonth = ospRule.GetWeek();
417                         if (dayOfWeekInMonth < 0)
418                         {
419                                 ++dayOfWeekInMonth;
420                         }
421                         break;
422                 case AFTER_THE_SPECIFIED_DAY:
423                 case BEFORE_THE_SPECIFIED_DAY:
424                         dayOfWeekInMonth *= ospRule.IsOnOrAfterDay()? 1 : -1;
425                         dayOfWeek = -dayOfWeek;
426                         break;
427                 }
428         }
429 }
430
431 result
432 _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRule* pIcuRule, TimeRule& ospRule)
433 {
434         if (pIcuRule)
435         {
436                 Month month = MONTH_UNDEFINED;
437                 int icuMonth = pIcuRule->getRuleMonth();
438                 if (icuMonth >= 0 && icuMonth <= 11)
439                 {
440                         month = static_cast< Month > (icuMonth + 1);
441                 }
442
443                 IcuDateTimeRule::DateRuleType dateRuleType = pIcuRule->getDateRuleType();
444                 int day = (dateRuleType == IcuDateTimeRule::DOW)? TimeRule::DAY_UNDEFINED : pIcuRule->getRuleDayOfMonth();
445
446                 Week week = WEEK_UNDEFINED;
447                 int icuWeek = pIcuRule->getRuleWeekInMonth();
448                 if (dateRuleType == IcuDateTimeRule::DOW)
449                 {
450                         week = (icuWeek == -1)? LAST_WEEK : static_cast< Week >(icuWeek);
451                 }
452
453                 DayOfWeek dayOfWeek = DAY_OF_WEEK_UNDEFINED;
454                 if (dateRuleType != IcuDateTimeRule::DOM)
455                 {
456                         dayOfWeek = static_cast< DayOfWeek >(pIcuRule->getRuleDayOfWeek());
457                 }
458
459                 bool onOrAfterDay = (dateRuleType == IcuDateTimeRule::DOW_LEQ_DOM)? false : true;
460
461                 int ruleMID = pIcuRule->getRuleMillisInDay();
462                 int hour = ruleMID / ONE_HOUR_IN_MILLISEC;
463                 int minute = (ruleMID % ONE_HOUR_IN_MILLISEC) / ONE_MIN_IN_MILLISEC;
464
465                 Tizen::System::TimeMode timeMode = Tizen::System::TIME_MODE_WALL;
466                 IcuDateTimeRule::TimeRuleType timeRuleType = pIcuRule->getTimeRuleType();
467                 if (timeRuleType == IcuDateTimeRule::UTC_TIME)
468                 {
469                         timeMode = Tizen::System::TIME_MODE_UTC;
470                 }
471
472                 if (timeRuleType == IcuDateTimeRule::STANDARD_TIME)
473                 {
474                         timeMode = Tizen::System::TIME_MODE_STANDARD;
475                 }
476
477                 ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);
478
479
480                 return E_SUCCESS;
481         }
482
483         return E_FAILURE;
484 }
485
486 };
487 };      // Tizen::Locales
488
489
490