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>
24 #include <FBaseSysLog.h>
25 #include <FLclTimeZone.h>
27 #include "FLcl_LocaleData.h"
28 #include "FLcl_TimeZoneImpl.h"
30 using namespace Tizen::Base;
32 namespace Tizen { namespace Locales
35 _TimeZoneImpl::_TimeZoneImpl(void)
36 : __icuTimeZone(0, "")
37 , __dstStartingYear(0)
38 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
39 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
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)
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)
59 SetDstRules(startRule, endRule, dstOffset);
62 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
63 : __icuTimeZone(otherTimeZone.__icuTimeZone)
64 , __dstStartingYear(otherTimeZone.__dstStartingYear)
65 , __startingRule(otherTimeZone.__startingRule)
66 , __endingRule(otherTimeZone.__endingRule)
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)
76 U_ICU_NAMESPACE::UnicodeString id;
77 __icuTimeZone.setID(icuTimeZone.getID(id));
78 __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
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)
87 U_ICU_NAMESPACE::UnicodeString id;
88 __icuTimeZone.setID(icuTimeZone.getID(id));
89 __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
91 U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(&icuTimeZone);
94 TimeRule startingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
95 TimeRule endingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
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);
105 result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), startingRule);
108 dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
109 GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), endingRule);
112 int dstStartingYear = pDst->getStartYear();
113 SetDstStartingYear(dstStartingYear);
119 SetDstRules(startingRule, endingRule, dstSaving);
124 _TimeZoneImpl::CloneN(void)
126 return new (std::nothrow) _TimeZoneImpl(*this);
130 _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
132 if (*this != otherTimeZone)
134 __icuTimeZone = otherTimeZone.__icuTimeZone;
135 __dstStartingYear = otherTimeZone.__dstStartingYear;
136 __startingRule = otherTimeZone.__startingRule;
137 __endingRule = otherTimeZone.__endingRule;
142 _TimeZoneImpl::~_TimeZoneImpl(void)
147 U_ICU_NAMESPACE::SimpleTimeZone
148 _TimeZoneImpl::GetIcuTimeZone(void) const
150 return __icuTimeZone;
155 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
157 return __icuTimeZone == otherTimeZone.__icuTimeZone;
161 _TimeZoneImpl::operator !=(const _TimeZoneImpl& otherTimeZone) const
163 return !(*this == otherTimeZone);
167 _TimeZoneImpl::Equals(const Object& obj) const
169 const _TimeZoneImpl* pTimeZoneImpl = dynamic_cast<const _TimeZoneImpl*>(&obj);
172 return (*this == *pTimeZoneImpl);
178 _TimeZoneImpl::GetHashCode(void) const
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();
190 _TimeZoneImpl::GetId(void) const
192 U_ICU_NAMESPACE::UnicodeString icuStr;
193 return _LocaleData::GetOspString(__icuTimeZone.getID(icuStr));
197 _TimeZoneImpl::SetId(const String& id)
199 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
200 __icuTimeZone.setID(icuStr);
204 _TimeZoneImpl::GetRawOffset(void) const
206 return __icuTimeZone.getRawOffset() / ONE_MIN_IN_MILLISEC;
210 _TimeZoneImpl::SetRawOffset(int rawOffset)
212 __icuTimeZone.setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
216 _TimeZoneImpl::GetDstStartingYear(void) const
218 return __dstStartingYear;
222 _TimeZoneImpl::SetDstStartingYear(int year)
224 __dstStartingYear = year;
225 __icuTimeZone.setStartYear(year);
229 _TimeZoneImpl::GetDstSavings(void) const
231 return __icuTimeZone.getDSTSavings() / ONE_MIN_IN_MILLISEC;
235 _TimeZoneImpl::SetDstSavings(int dstSavings)
237 UErrorCode ec = U_ZERO_ERROR;
238 __icuTimeZone.setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
242 _TimeZoneImpl::GetDstStartingRule(void) const
244 return __startingRule.GetMonth() != MONTH_UNDEFINED ? &__startingRule : null;
248 _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
251 int dayOfWeekInMonth = 0;
256 UErrorCode ec = U_ZERO_ERROR;
257 GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
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;
265 _TimeZoneImpl::GetDstEndingRule(void) const
267 return __endingRule.GetMonth() != MONTH_UNDEFINED ? &__endingRule : null;
271 _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
274 int dayOfWeekInMonth = 0;
279 UErrorCode ec = U_ZERO_ERROR;
280 GetIcuTimeRuleValue(endRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
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;
288 _TimeZoneImpl::SetDstRules(const TimeRule& startRule, const TimeRule& endRule, int dstSavings)
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);
301 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
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;
311 _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
315 date.SetValue(ts.GetTicks());
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;
326 _TimeZoneImpl::IsDstUsed(void) const
328 return __icuTimeZone.useDaylightTime();
332 _TimeZoneImpl::GetTimeZoneImpl(const TimeZone& ospTimeZone)
334 return ospTimeZone.__pTimeZoneImpl;
338 _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
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");
344 U_ICU_NAMESPACE::UnicodeString retIcuStr;
345 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
346 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
348 U_ICU_NAMESPACE::SimpleTimeZone icuTimeZone(pIcuTimeZone->getRawOffset(), icuStr);
349 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(icuTimeZone));
352 delete timeZone.__pTimeZoneImpl;
353 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
357 return E_INVALID_ARG;
361 _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Locales::TimeZone& timeZone)
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");
367 U_ICU_NAMESPACE::UnicodeString retIcuStr;
368 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
369 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
371 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(*pIcuTimeZone, _LocaleData::GetIcuDate(utcTime)));
374 delete timeZone.__pTimeZoneImpl;
375 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
379 return E_INVALID_ARG;
383 _TimeZoneImpl::GetIcuTimeRuleValue(const TimeRule& ospRule, int& month, int& dayOfWeekInMonth, int& dayOfWeek, int& time, int& mode)
385 if (ospRule.GetMonth() != MONTH_UNDEFINED)
387 month = ospRule.GetMonth() - 1;
389 int ospDay = ospRule.GetDay();
390 dayOfWeekInMonth = (ospDay == TimeRule::DAY_UNDEFINED)? 0 : ospDay;
392 int ospDayOfWeek = ospRule.GetDayOfWeek();
393 dayOfWeek = (ospDayOfWeek == WEEK_UNDEFINED)? 0 : ospDayOfWeek;
395 time = ospRule.GetHour() * ONE_HOUR_IN_MILLISEC + ospRule.GetMinute() * ONE_MIN_IN_MILLISEC;
397 int ospTimeMode = ospRule.GetTimeMode();
398 mode = IcuDateTimeRule::WALL_TIME;
399 if (ospTimeMode == Tizen::System::TIME_MODE_UTC)
401 mode = IcuDateTimeRule::UTC_TIME;
404 if (ospTimeMode == Tizen::System::TIME_MODE_STANDARD)
406 mode = IcuDateTimeRule::STANDARD_TIME;
409 switch (ospRule.GetRuleMode())
412 case BACKWARD_FROM_END_OF_MONTH:
415 case DAY_OF_WEEK_IN_MONTH:
416 dayOfWeekInMonth = ospRule.GetWeek();
417 if (dayOfWeekInMonth < 0)
422 case AFTER_THE_SPECIFIED_DAY:
423 case BEFORE_THE_SPECIFIED_DAY:
424 dayOfWeekInMonth *= ospRule.IsOnOrAfterDay()? 1 : -1;
425 dayOfWeek = -dayOfWeek;
432 _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRule* pIcuRule, TimeRule& ospRule)
436 Month month = MONTH_UNDEFINED;
437 int icuMonth = pIcuRule->getRuleMonth();
438 if (icuMonth >= 0 && icuMonth <= 11)
440 month = static_cast< Month > (icuMonth + 1);
443 IcuDateTimeRule::DateRuleType dateRuleType = pIcuRule->getDateRuleType();
444 int day = (dateRuleType == IcuDateTimeRule::DOW)? TimeRule::DAY_UNDEFINED : pIcuRule->getRuleDayOfMonth();
446 Week week = WEEK_UNDEFINED;
447 int icuWeek = pIcuRule->getRuleWeekInMonth();
448 if (dateRuleType == IcuDateTimeRule::DOW)
450 week = (icuWeek == -1)? LAST_WEEK : static_cast< Week >(icuWeek);
453 DayOfWeek dayOfWeek = DAY_OF_WEEK_UNDEFINED;
454 if (dateRuleType != IcuDateTimeRule::DOM)
456 dayOfWeek = static_cast< DayOfWeek >(pIcuRule->getRuleDayOfWeek());
459 bool onOrAfterDay = (dateRuleType == IcuDateTimeRule::DOW_LEQ_DOM)? false : true;
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;
465 Tizen::System::TimeMode timeMode = Tizen::System::TIME_MODE_WALL;
466 IcuDateTimeRule::TimeRuleType timeRuleType = pIcuRule->getTimeRuleType();
467 if (timeRuleType == IcuDateTimeRule::UTC_TIME)
469 timeMode = Tizen::System::TIME_MODE_UTC;
472 if (timeRuleType == IcuDateTimeRule::STANDARD_TIME)
474 timeMode = Tizen::System::TIME_MODE_STANDARD;
477 ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);