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>
27 #include <FBaseInteger.h>
28 #include <FBaseSysLog.h>
29 #include <FLclTimeZone.h>
31 #include "FLcl_LocaleData.h"
32 #include "FLcl_TimeZoneImpl.h"
34 typedef U_ICU_NAMESPACE::TimeZone IcuTimeZone;
35 typedef U_ICU_NAMESPACE::BasicTimeZone IcuBasicTimeZone;
36 typedef U_ICU_NAMESPACE::SimpleTimeZone IcuSimpleTimeZone;
37 typedef U_ICU_NAMESPACE::InitialTimeZoneRule IcuInitialTimeZoneRule;
38 typedef U_ICU_NAMESPACE::AnnualTimeZoneRule IcuAnnualTimeZoneRule;
39 typedef U_ICU_NAMESPACE::DateTimeRule IcuDateTimeRule;
45 AFTER_THE_SPECIFIED_DAY,
46 BEFORE_THE_SPECIFIED_DAY,
47 BACKWARD_FROM_END_OF_MONTH
50 using namespace Tizen::Base;
52 namespace Tizen { namespace Locales
55 _TimeZoneImpl::_TimeZoneImpl(void)
56 : __pIcuTimeZone(null)
57 , __dstStartingYear(0)
58 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
59 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
60 , __isCustomizing(true)
62 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(0, "");
63 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
66 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id)
67 : __pIcuTimeZone(null)
68 , __dstStartingYear(0)
69 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
70 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
71 , __isCustomizing(true)
73 UnicodeString icuId(_LocaleData::GetIcuString(id));
74 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
75 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
78 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id, const TimeRule& startRule, const TimeRule& endRule, int dstOffset)
79 : __pIcuTimeZone(null)
80 , __dstStartingYear(0)
81 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
82 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
83 , __isCustomizing(true)
85 UnicodeString icuId(_LocaleData::GetIcuString(id));
86 __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
87 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
88 SetDstRules(startRule, endRule, dstOffset);
91 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
92 : __pIcuTimeZone(null)
93 , __dstStartingYear(otherTimeZone.__dstStartingYear)
94 , __startingRule(otherTimeZone.__startingRule)
95 , __endingRule(otherTimeZone.__endingRule)
96 , __isCustomizing(otherTimeZone.__isCustomizing)
98 __pIcuTimeZone = otherTimeZone.__pIcuTimeZone->clone();
99 SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
102 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone)
103 : __pIcuTimeZone(null)
104 , __dstStartingYear(0)
105 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
106 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
107 , __isCustomizing(true)
109 __pIcuTimeZone = pIcuTimeZone;
112 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone, UDate icuDate)
113 : __pIcuTimeZone(null)
114 , __dstStartingYear(0)
115 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
116 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
117 , __isCustomizing(false)
119 __pIcuTimeZone = pIcuTimeZone;
121 U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(pIcuTimeZone);
124 UErrorCode status = U_ZERO_ERROR;
125 U_ICU_NAMESPACE::InitialTimeZoneRule* pInitial = null;
126 U_ICU_NAMESPACE::AnnualTimeZoneRule* pStd = null;
127 U_ICU_NAMESPACE::AnnualTimeZoneRule* pDst = null;
128 pIcuTz->getSimpleRulesNear(icuDate, pInitial, pStd, pDst, status);
132 result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), __startingRule);
135 GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), __endingRule);
136 __dstStartingYear = pDst->getStartYear();
147 _TimeZoneImpl::CloneN(void)
149 return new (std::nothrow) _TimeZoneImpl(*this);
153 _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
155 if (*this != otherTimeZone)
157 __pIcuTimeZone = otherTimeZone.__pIcuTimeZone;
158 __dstStartingYear = otherTimeZone.__dstStartingYear;
159 __startingRule = otherTimeZone.__startingRule;
160 __endingRule = otherTimeZone.__endingRule;
161 __isCustomizing = otherTimeZone.__isCustomizing;
166 _TimeZoneImpl::~_TimeZoneImpl(void)
170 delete __pIcuTimeZone;
174 U_ICU_NAMESPACE::TimeZone*
175 _TimeZoneImpl::GetIcuTimeZone(void) const
177 return __pIcuTimeZone;
182 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
184 return *__pIcuTimeZone == *otherTimeZone.__pIcuTimeZone;
188 _TimeZoneImpl::operator !=(const _TimeZoneImpl& otherTimeZone) const
190 return !(*this == otherTimeZone);
194 _TimeZoneImpl::Equals(const Object& obj) const
196 const _TimeZoneImpl* pTimeZoneImpl = dynamic_cast<const _TimeZoneImpl*>(&obj);
199 return (*this == *pTimeZoneImpl);
205 _TimeZoneImpl::GetHashCode(void) const
207 int hashCode = GetId().GetHashCode();
208 int customizing = (__isCustomizing == false) ? 0 : __dstStartingYear;
209 Integer intValues = GetRawOffset() + GetDstSavings() + IsDstUsed() + customizing;
210 hashCode = (hashCode << 5) - hashCode + intValues.GetHashCode();
211 hashCode = (hashCode << 5) - hashCode + __startingRule.GetHashCode();
212 hashCode = (hashCode << 5) - hashCode + __endingRule.GetHashCode();
218 _TimeZoneImpl::GetId(void) const
220 U_ICU_NAMESPACE::UnicodeString icuStr;
221 __pIcuTimeZone->getID(icuStr);
222 return _LocaleData::GetOspString(icuStr);
226 _TimeZoneImpl::SetId(const String& id)
228 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
229 __pIcuTimeZone->setID(icuStr);
233 _TimeZoneImpl::GetRawOffset(void) const
235 return __pIcuTimeZone->getRawOffset() / ONE_MIN_IN_MILLISEC;
239 _TimeZoneImpl::SetRawOffset(int rawOffset)
241 __pIcuTimeZone->setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
245 _TimeZoneImpl::GetDstStartingYear(void) const
247 return __dstStartingYear;
251 _TimeZoneImpl::SetDstStartingYear(int year)
253 __dstStartingYear = year;
254 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
258 U_ICU_NAMESPACE::UnicodeString id;
259 __pIcuTimeZone->getID(id);
260 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
261 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
262 delete __pIcuTimeZone;
263 __pIcuTimeZone = pStz;
266 pStz->setStartYear(year);
267 __isCustomizing = true;
271 _TimeZoneImpl::GetDstSavings(void) const
273 return __pIcuTimeZone->getDSTSavings() / ONE_MIN_IN_MILLISEC;
277 _TimeZoneImpl::SetDstSavings(int dstSavings)
279 UErrorCode ec = U_ZERO_ERROR;
281 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
285 U_ICU_NAMESPACE::UnicodeString id;
286 __pIcuTimeZone->getID(id);
287 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
288 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
289 delete __pIcuTimeZone;
290 __pIcuTimeZone = pStz;
292 pStz->setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
293 __isCustomizing = true;
297 _TimeZoneImpl::GetDstStartingRule(void) const
299 return __startingRule.GetMonth() != MONTH_UNDEFINED ? &__startingRule : null;
303 _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
306 int dayOfWeekInMonth = 0;
311 UErrorCode ec = U_ZERO_ERROR;
312 GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
314 U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
315 U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
319 U_ICU_NAMESPACE::UnicodeString id;
320 __pIcuTimeZone->getID(id);
321 pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
322 SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
323 delete __pIcuTimeZone;
324 __pIcuTimeZone = pStz;
327 pStz->setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
328 __startingRule = startRule;
329 __isCustomizing = true;
333 _TimeZoneImpl::GetDstEndingRule(void) const
335 return __endingRule.GetMonth() != MONTH_UNDEFINED ? &__endingRule : null;
339 _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
342 int dayOfWeekInMonth = 0;
347 UErrorCode ec = U_ZERO_ERROR;
348 GetIcuTimeRuleValue(endRule, 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->setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
364 __endingRule = endRule;
365 __isCustomizing = true;
369 _TimeZoneImpl::SetDstRules(const TimeRule& startRule, const TimeRule& endRule, int dstSavings)
371 SysTryReturnResult(NID_LCL, dstSavings >= 0,
372 E_OUT_OF_RANGE, "dstSavings [%d] should be greater or equal to than 0", dstSavings);
373 SysTryReturnResult(NID_LCL, dstSavings < ONE_DAY_IN_MINUTE,
374 E_OUT_OF_RANGE, "dstSavings [%d] should be greater than %d", dstSavings, ONE_DAY_IN_MINUTE);
375 SetDstStartingRule(startRule);
376 SetDstEndingRule(endRule);
377 SetDstSavings(dstSavings);
382 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
384 UErrorCode ec = U_ZERO_ERROR;
385 __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
386 rawOffset /= ONE_MIN_IN_MILLISEC;
387 dstOffset /= ONE_MIN_IN_MILLISEC;
388 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
392 _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
396 date.SetValue(ts.GetTicks());
400 UErrorCode ec = U_ZERO_ERROR;
401 __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
402 offset = (rawOffset + dstOffset) / ONE_MIN_IN_MILLISEC;
403 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
407 _TimeZoneImpl::IsDstUsed(void) const
409 return __pIcuTimeZone->useDaylightTime();
413 _TimeZoneImpl::GetTimeZoneImpl(const TimeZone& ospTimeZone)
415 return ospTimeZone.__pTimeZoneImpl;
419 _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
421 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
422 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
423 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
425 U_ICU_NAMESPACE::UnicodeString retIcuStr;
426 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
427 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
429 std::unique_ptr<U_ICU_NAMESPACE::SimpleTimeZone> pIcuSimpleTimeZone(new U_ICU_NAMESPACE::SimpleTimeZone(pIcuTimeZone->getRawOffset(), icuStr));
430 SysTryReturnResult(NID_LCL, pIcuSimpleTimeZone, E_OUT_OF_MEMORY, "It is enough memory.");
431 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuSimpleTimeZone.get()));
432 SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
434 delete timeZone.__pTimeZoneImpl;
435 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
436 pIcuSimpleTimeZone.release();
441 _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Locales::TimeZone& timeZone)
443 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
444 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
445 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
447 U_ICU_NAMESPACE::UnicodeString retIcuStr;
448 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
449 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
451 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuTimeZone.get(), _LocaleData::GetIcuDate(utcTime)));
452 SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
454 delete timeZone.__pTimeZoneImpl;
455 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
456 pIcuTimeZone.release();
461 _TimeZoneImpl::GetIcuTimeRuleValue(const TimeRule& ospRule, int& month, int& dayOfWeekInMonth, int& dayOfWeek, int& time, int& mode)
463 if (ospRule.GetMonth() != MONTH_UNDEFINED)
465 month = ospRule.GetMonth() - 1;
467 int ospDay = ospRule.GetDay();
468 dayOfWeekInMonth = (ospDay == TimeRule::DAY_UNDEFINED)? 0 : ospDay;
470 int ospDayOfWeek = ospRule.GetDayOfWeek();
471 dayOfWeek = (ospDayOfWeek == WEEK_UNDEFINED)? 0 : ospDayOfWeek;
473 time = ospRule.GetHour() * ONE_HOUR_IN_MILLISEC + ospRule.GetMinute() * ONE_MIN_IN_MILLISEC;
475 int ospTimeMode = ospRule.GetTimeMode();
476 mode = IcuDateTimeRule::WALL_TIME;
477 if (ospTimeMode == Tizen::System::TIME_MODE_UTC)
479 mode = IcuDateTimeRule::UTC_TIME;
482 if (ospTimeMode == Tizen::System::TIME_MODE_STANDARD)
484 mode = IcuDateTimeRule::STANDARD_TIME;
487 switch (ospRule.GetRuleMode())
490 case BACKWARD_FROM_END_OF_MONTH:
493 case DAY_OF_WEEK_IN_MONTH:
494 dayOfWeekInMonth = ospRule.GetWeek();
495 if (dayOfWeekInMonth < 0)
500 case AFTER_THE_SPECIFIED_DAY:
501 case BEFORE_THE_SPECIFIED_DAY:
502 dayOfWeekInMonth *= ospRule.IsOnOrAfterDay()? 1 : -1;
503 dayOfWeek = -dayOfWeek;
510 _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRule* pIcuRule, TimeRule& ospRule)
514 Month month = MONTH_UNDEFINED;
515 int icuMonth = pIcuRule->getRuleMonth();
516 if (icuMonth >= 0 && icuMonth <= 11)
518 month = static_cast< Month > (icuMonth + 1);
521 IcuDateTimeRule::DateRuleType dateRuleType = pIcuRule->getDateRuleType();
522 int day = (dateRuleType == IcuDateTimeRule::DOW)? TimeRule::DAY_UNDEFINED : pIcuRule->getRuleDayOfMonth();
524 Week week = WEEK_UNDEFINED;
525 int icuWeek = pIcuRule->getRuleWeekInMonth();
526 if (dateRuleType == IcuDateTimeRule::DOW)
528 week = (icuWeek == -1)? LAST_WEEK : static_cast< Week >(icuWeek);
531 DayOfWeek dayOfWeek = DAY_OF_WEEK_UNDEFINED;
532 if (dateRuleType != IcuDateTimeRule::DOM)
534 dayOfWeek = static_cast< DayOfWeek >(pIcuRule->getRuleDayOfWeek());
537 bool onOrAfterDay = (dateRuleType == IcuDateTimeRule::DOW_LEQ_DOM)? false : true;
539 int ruleMID = pIcuRule->getRuleMillisInDay();
540 int hour = ruleMID / ONE_HOUR_IN_MILLISEC;
541 int minute = (ruleMID % ONE_HOUR_IN_MILLISEC) / ONE_MIN_IN_MILLISEC;
543 Tizen::System::TimeMode timeMode = Tizen::System::TIME_MODE_WALL;
544 IcuDateTimeRule::TimeRuleType timeRuleType = pIcuRule->getTimeRuleType();
545 if (timeRuleType == IcuDateTimeRule::UTC_TIME)
547 timeMode = Tizen::System::TIME_MODE_UTC;
550 if (timeRuleType == IcuDateTimeRule::STANDARD_TIME)
552 timeMode = Tizen::System::TIME_MODE_STANDARD;
555 ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);