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