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 FLcl_TimeZoneImpl.cpp
19 * @brief This is the implementation file for _TimeZoneImpl class.
22 #include <unique_ptr.h>
23 #include <unicode/timezone.h>
24 #include <unicode/basictz.h>
25 #include <unicode/simpletz.h>
26 #include <unicode/tztrans.h>
27 #include <unicode/tzrule.h>
29 #include <FBaseInteger.h>
30 #include <FBaseSysLog.h>
31 #include <FLclTimeZone.h>
33 #include "FLcl_LocaleData.h"
34 #include "FLcl_TimeZoneImpl.h"
36 typedef U_ICU_NAMESPACE::TimeZone IcuTimeZone;
37 typedef U_ICU_NAMESPACE::BasicTimeZone IcuBasicTimeZone;
38 typedef U_ICU_NAMESPACE::SimpleTimeZone IcuSimpleTimeZone;
39 typedef U_ICU_NAMESPACE::InitialTimeZoneRule IcuInitialTimeZoneRule;
40 typedef U_ICU_NAMESPACE::AnnualTimeZoneRule IcuAnnualTimeZoneRule;
41 typedef U_ICU_NAMESPACE::DateTimeRule IcuDateTimeRule;
47 AFTER_THE_SPECIFIED_DAY,
48 BEFORE_THE_SPECIFIED_DAY,
49 BACKWARD_FROM_END_OF_MONTH
52 using namespace Tizen::Base;
54 namespace Tizen { namespace Locales
57 _TimeZoneImpl::_TimeZoneImpl(void)
58 : __pIcuTimeZone(null)
60 , __dstStartingYear(0)
61 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
62 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
63 , __isCustomizing(true)
65 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(0, "");
66 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
69 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id)
70 : __pIcuTimeZone(null)
72 , __dstStartingYear(0)
73 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
74 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
75 , __isCustomizing(true)
77 UnicodeString icuId(_LocaleData::GetIcuString(id));
78 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
79 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
82 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id, const TimeRule& startRule, const TimeRule& endRule, int dstOffset)
83 : __pIcuTimeZone(null)
84 , __dstSaving(dstOffset)
85 , __dstStartingYear(0)
86 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
87 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
88 , __isCustomizing(true)
90 UnicodeString icuId(_LocaleData::GetIcuString(id));
91 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
92 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
93 SetDstRules(startRule, endRule, dstOffset);
96 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
97 : __pIcuTimeZone(null)
98 , __dstSaving(otherTimeZone.__dstSaving)
99 , __dstStartingYear(otherTimeZone.__dstStartingYear)
100 , __startingRule(otherTimeZone.__startingRule)
101 , __endingRule(otherTimeZone.__endingRule)
102 , __isCustomizing(otherTimeZone.__isCustomizing)
104 __pIcuTimeZone = otherTimeZone.__pIcuTimeZone->clone();
105 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
108 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone)
109 : __pIcuTimeZone(null)
111 , __dstStartingYear(0)
112 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
113 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
114 , __isCustomizing(true)
116 __pIcuTimeZone = pIcuTimeZone;
119 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone, UDate icuDate)
120 : __pIcuTimeZone(null)
122 , __dstStartingYear(0)
123 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
124 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
125 , __isCustomizing(false)
127 __pIcuTimeZone = pIcuTimeZone;
128 U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(pIcuTimeZone);
131 UErrorCode status = U_ZERO_ERROR;
132 U_ICU_NAMESPACE::InitialTimeZoneRule* pInitial = null;
133 U_ICU_NAMESPACE::AnnualTimeZoneRule* pStd = null;
134 U_ICU_NAMESPACE::AnnualTimeZoneRule* pDst = null;
135 pIcuTz->getSimpleRulesNear(icuDate, pInitial, pStd, pDst, status);
139 result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), __startingRule);
142 GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), __endingRule);
143 __dstStartingYear = pDst->getStartYear();
144 __dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
149 U_ICU_NAMESPACE::TimeZoneTransition transition;
150 bool result = pIcuTz->getPreviousTransition(icuDate, true, transition);
153 const U_ICU_NAMESPACE::TimeZoneRule* pTzFromRule = transition.getFrom();
154 const U_ICU_NAMESPACE::TimeZoneRule* pTzToRule = transition.getTo();
156 if (pTzFromRule->getDSTSavings())
158 __dstSaving = pTzFromRule->getDSTSavings() / ONE_MIN_IN_MILLISEC;
160 else if (pTzToRule->getDSTSavings())
162 __dstSaving = pTzToRule->getDSTSavings() / ONE_MIN_IN_MILLISEC;
164 else //if (pTzFromRule->getDSTSavings() == 0 && pTzToRule->getDSTSavings() == 0)
177 _TimeZoneImpl::CloneN(void)
179 return new (std::nothrow) _TimeZoneImpl(*this);
183 _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
185 if (*this != otherTimeZone)
187 __pIcuTimeZone = otherTimeZone.__pIcuTimeZone;
188 __dstSaving = otherTimeZone.__dstSaving;
189 __dstStartingYear = otherTimeZone.__dstStartingYear;
190 __startingRule = otherTimeZone.__startingRule;
191 __endingRule = otherTimeZone.__endingRule;
192 __isCustomizing = otherTimeZone.__isCustomizing;
197 _TimeZoneImpl::~_TimeZoneImpl(void)
201 delete __pIcuTimeZone;
205 U_ICU_NAMESPACE::TimeZone*
206 _TimeZoneImpl::GetIcuTimeZone(void) const
208 return __pIcuTimeZone;
213 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
215 return *__pIcuTimeZone == *otherTimeZone.__pIcuTimeZone;
219 _TimeZoneImpl::operator !=(const _TimeZoneImpl& otherTimeZone) const
221 return !(*this == otherTimeZone);
225 _TimeZoneImpl::Equals(const Object& obj) const
227 const _TimeZoneImpl* pTimeZoneImpl = dynamic_cast<const _TimeZoneImpl*>(&obj);
230 return (*this == *pTimeZoneImpl);
236 _TimeZoneImpl::GetHashCode(void) const
238 int hashCode = GetId().GetHashCode();
239 int customizing = (__isCustomizing == false) ? 0 : __dstStartingYear;
240 Integer intValues = GetRawOffset() + GetDstSavings() + IsDstUsed() + customizing;
241 hashCode = (hashCode << 5) - hashCode + intValues.GetHashCode();
242 hashCode = (hashCode << 5) - hashCode + __startingRule.GetHashCode();
243 hashCode = (hashCode << 5) - hashCode + __endingRule.GetHashCode();
249 _TimeZoneImpl::GetId(void) const
251 U_ICU_NAMESPACE::UnicodeString icuStr;
252 __pIcuTimeZone->getID(icuStr);
253 return _LocaleData::GetOspString(icuStr);
257 _TimeZoneImpl::SetId(const String& id)
259 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
260 __pIcuTimeZone->setID(icuStr);
264 _TimeZoneImpl::GetRawOffset(void) const
266 return __pIcuTimeZone->getRawOffset() / ONE_MIN_IN_MILLISEC;
270 _TimeZoneImpl::SetRawOffset(int rawOffset)
272 __pIcuTimeZone->setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
276 _TimeZoneImpl::GetDstStartingYear(void) const
278 return __dstStartingYear;
282 _TimeZoneImpl::SetDstStartingYear(int year)
284 __dstStartingYear = year;
285 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
289 U_ICU_NAMESPACE::UnicodeString id;
290 __pIcuTimeZone->getID(id);
291 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
292 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
293 delete __pIcuTimeZone;
294 __pIcuTimeZone = pStz;
297 pStz->setStartYear(year);
298 __isCustomizing = true;
302 _TimeZoneImpl::GetDstSavings(void) const
306 return __pIcuTimeZone->getDSTSavings() / ONE_MIN_IN_MILLISEC;
312 _TimeZoneImpl::SetDstSavings(int dstSavings)
314 UErrorCode ec = U_ZERO_ERROR;
316 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
320 U_ICU_NAMESPACE::UnicodeString id;
321 __pIcuTimeZone->getID(id);
322 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
323 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
324 delete __pIcuTimeZone;
325 __pIcuTimeZone = pStz;
327 pStz->setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
328 __dstSaving = dstSavings;
329 __isCustomizing = true;
333 _TimeZoneImpl::GetDstStartingRule(void) const
335 return __startingRule.GetMonth() != MONTH_UNDEFINED ? &__startingRule : null;
339 _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
342 int dayOfWeekInMonth = 0;
347 UErrorCode ec = U_ZERO_ERROR;
348 GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
350 U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
351 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
355 U_ICU_NAMESPACE::UnicodeString id;
356 __pIcuTimeZone->getID(id);
357 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
358 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
359 delete __pIcuTimeZone;
360 __pIcuTimeZone = pStz;
363 pStz->setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
364 __startingRule = startRule;
365 __isCustomizing = true;
369 _TimeZoneImpl::GetDstEndingRule(void) const
371 return __endingRule.GetMonth() != MONTH_UNDEFINED ? &__endingRule : null;
375 _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
378 int dayOfWeekInMonth = 0;
383 UErrorCode ec = U_ZERO_ERROR;
384 GetIcuTimeRuleValue(endRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
386 U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
387 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
391 U_ICU_NAMESPACE::UnicodeString id;
392 __pIcuTimeZone->getID(id);
393 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
394 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
395 delete __pIcuTimeZone;
396 __pIcuTimeZone = pStz;
399 pStz->setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
400 __endingRule = endRule;
401 __isCustomizing = true;
405 _TimeZoneImpl::SetDstRules(const TimeRule& startRule, const TimeRule& endRule, int dstSavings)
407 SysTryReturnResult(NID_LCL, dstSavings >= 0,
408 E_OUT_OF_RANGE, "dstSavings [%d] should be greater or equal to than 0", dstSavings);
409 SysTryReturnResult(NID_LCL, dstSavings < ONE_DAY_IN_MINUTE,
410 E_OUT_OF_RANGE, "dstSavings [%d] should be greater than %d", dstSavings, ONE_DAY_IN_MINUTE);
411 SetDstStartingRule(startRule);
412 SetDstEndingRule(endRule);
413 SetDstSavings(dstSavings);
418 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
420 UErrorCode ec = U_ZERO_ERROR;
421 __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
422 rawOffset /= ONE_MIN_IN_MILLISEC;
423 dstOffset /= ONE_MIN_IN_MILLISEC;
424 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
428 _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
432 result r = date.SetValue(ts.GetTicks());
433 SysTryReturnResult(NID_LCL, r == E_SUCCESS, E_INVALID_ARG, "It is an invalid argument.");
437 UErrorCode ec = U_ZERO_ERROR;
438 __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
439 offset = (rawOffset + dstOffset) / ONE_MIN_IN_MILLISEC;
440 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
444 _TimeZoneImpl::IsDstUsed(void) const
446 return __pIcuTimeZone->useDaylightTime();
450 _TimeZoneImpl::GetTimeZoneImpl(const TimeZone& ospTimeZone)
452 return ospTimeZone.__pTimeZoneImpl;
456 _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
458 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
459 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
460 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
462 U_ICU_NAMESPACE::UnicodeString retIcuStr;
463 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
464 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
466 std::unique_ptr<U_ICU_NAMESPACE::SimpleTimeZone> pIcuSimpleTimeZone(new U_ICU_NAMESPACE::SimpleTimeZone(pIcuTimeZone->getRawOffset(), icuStr));
467 SysTryReturnResult(NID_LCL, pIcuSimpleTimeZone, E_OUT_OF_MEMORY, "It is enough memory.");
468 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuSimpleTimeZone.get()));
469 SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
471 delete timeZone.__pTimeZoneImpl;
472 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
473 pIcuSimpleTimeZone.release();
478 _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Locales::TimeZone& timeZone)
480 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
481 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
482 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
484 U_ICU_NAMESPACE::UnicodeString retIcuStr;
485 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
486 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
488 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuTimeZone.get(), _LocaleData::GetIcuDate(utcTime)));
489 SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
491 delete timeZone.__pTimeZoneImpl;
492 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
493 pIcuTimeZone.release();
498 _TimeZoneImpl::GetIcuTimeRuleValue(const TimeRule& ospRule, int& month, int& dayOfWeekInMonth, int& dayOfWeek, int& time, int& mode)
500 if (ospRule.GetMonth() != MONTH_UNDEFINED)
502 month = ospRule.GetMonth() - 1;
504 int ospDay = ospRule.GetDay();
505 dayOfWeekInMonth = (ospDay == TimeRule::DAY_UNDEFINED)? 0 : ospDay;
507 int ospDayOfWeek = ospRule.GetDayOfWeek();
508 dayOfWeek = (ospDayOfWeek == WEEK_UNDEFINED)? 0 : ospDayOfWeek;
510 time = ospRule.GetHour() * ONE_HOUR_IN_MILLISEC + ospRule.GetMinute() * ONE_MIN_IN_MILLISEC;
512 int ospTimeMode = ospRule.GetTimeMode();
513 mode = IcuDateTimeRule::WALL_TIME;
514 if (ospTimeMode == Tizen::System::TIME_MODE_UTC)
516 mode = IcuDateTimeRule::UTC_TIME;
519 if (ospTimeMode == Tizen::System::TIME_MODE_STANDARD)
521 mode = IcuDateTimeRule::STANDARD_TIME;
524 switch (ospRule.GetRuleMode())
527 case BACKWARD_FROM_END_OF_MONTH:
530 case DAY_OF_WEEK_IN_MONTH:
531 dayOfWeekInMonth = ospRule.GetWeek();
532 if (dayOfWeekInMonth < 0)
537 case AFTER_THE_SPECIFIED_DAY:
538 case BEFORE_THE_SPECIFIED_DAY:
539 dayOfWeekInMonth *= ospRule.IsOnOrAfterDay()? 1 : -1;
540 dayOfWeek = -dayOfWeek;
547 _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRule* pIcuRule, TimeRule& ospRule)
551 Month month = MONTH_UNDEFINED;
552 int icuMonth = pIcuRule->getRuleMonth();
553 if (icuMonth >= 0 && icuMonth <= 11)
555 month = static_cast< Month > (icuMonth + 1);
558 IcuDateTimeRule::DateRuleType dateRuleType = pIcuRule->getDateRuleType();
559 int day = (dateRuleType == IcuDateTimeRule::DOW)? TimeRule::DAY_UNDEFINED : pIcuRule->getRuleDayOfMonth();
561 Week week = WEEK_UNDEFINED;
562 int icuWeek = pIcuRule->getRuleWeekInMonth();
563 if (dateRuleType == IcuDateTimeRule::DOW)
565 week = (icuWeek == -1)? LAST_WEEK : static_cast< Week >(icuWeek);
568 DayOfWeek dayOfWeek = DAY_OF_WEEK_UNDEFINED;
569 if (dateRuleType != IcuDateTimeRule::DOM)
571 dayOfWeek = static_cast< DayOfWeek >(pIcuRule->getRuleDayOfWeek());
574 bool onOrAfterDay = (dateRuleType == IcuDateTimeRule::DOW_LEQ_DOM)? false : true;
576 int ruleMID = pIcuRule->getRuleMillisInDay();
577 int hour = ruleMID / ONE_HOUR_IN_MILLISEC;
578 int minute = (ruleMID % ONE_HOUR_IN_MILLISEC) / ONE_MIN_IN_MILLISEC;
580 Tizen::System::TimeMode timeMode = Tizen::System::TIME_MODE_WALL;
581 IcuDateTimeRule::TimeRuleType timeRuleType = pIcuRule->getTimeRuleType();
582 if (timeRuleType == IcuDateTimeRule::UTC_TIME)
584 timeMode = Tizen::System::TIME_MODE_UTC;
587 if (timeRuleType == IcuDateTimeRule::STANDARD_TIME)
589 timeMode = Tizen::System::TIME_MODE_STANDARD;
592 ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);