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 : __icuTimeZone(0, "")
57 , __dstStartingYear(0)
58 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
59 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
64 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id)
65 : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
66 , __dstStartingYear(0)
67 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
68 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
73 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id, const TimeRule& startRule, const TimeRule& endRule, int dstOffset)
74 : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
75 , __dstStartingYear(0)
76 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
77 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
79 SetDstRules(startRule, endRule, dstOffset);
82 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
83 : __icuTimeZone(otherTimeZone.__icuTimeZone)
84 , __dstStartingYear(otherTimeZone.__dstStartingYear)
85 , __startingRule(otherTimeZone.__startingRule)
86 , __endingRule(otherTimeZone.__endingRule)
90 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone)
91 : __icuTimeZone(0, "")
92 , __dstStartingYear(0)
93 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
94 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
96 U_ICU_NAMESPACE::UnicodeString id;
97 __icuTimeZone.setID(icuTimeZone.getID(id));
98 __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
101 _TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone, UDate icuDate)
102 : __icuTimeZone(0, "")
103 , __dstStartingYear(0)
104 , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
105 , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
107 U_ICU_NAMESPACE::UnicodeString id;
108 __icuTimeZone.setID(icuTimeZone.getID(id));
109 __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
111 U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(&icuTimeZone);
114 TimeRule startingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
115 TimeRule endingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
118 UErrorCode status = U_ZERO_ERROR;
119 U_ICU_NAMESPACE::InitialTimeZoneRule* pInitial = null;
120 U_ICU_NAMESPACE::AnnualTimeZoneRule* pStd = null;
121 U_ICU_NAMESPACE::AnnualTimeZoneRule* pDst = null;
122 pIcuTz->getSimpleRulesNear(icuDate, pInitial, pStd, pDst, status);
125 result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), startingRule);
128 dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
129 GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), endingRule);
132 int dstStartingYear = pDst->getStartYear();
133 SetDstStartingYear(dstStartingYear);
139 SetDstRules(startingRule, endingRule, dstSaving);
144 _TimeZoneImpl::CloneN(void)
146 return new (std::nothrow) _TimeZoneImpl(*this);
150 _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
152 if (*this != otherTimeZone)
154 __icuTimeZone = otherTimeZone.__icuTimeZone;
155 __dstStartingYear = otherTimeZone.__dstStartingYear;
156 __startingRule = otherTimeZone.__startingRule;
157 __endingRule = otherTimeZone.__endingRule;
162 _TimeZoneImpl::~_TimeZoneImpl(void)
167 U_ICU_NAMESPACE::SimpleTimeZone
168 _TimeZoneImpl::GetIcuTimeZone(void) const
170 return __icuTimeZone;
175 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
177 return __icuTimeZone == otherTimeZone.__icuTimeZone;
181 _TimeZoneImpl::operator !=(const _TimeZoneImpl& otherTimeZone) const
183 return !(*this == otherTimeZone);
187 _TimeZoneImpl::Equals(const Object& obj) const
189 const _TimeZoneImpl* pTimeZoneImpl = dynamic_cast<const _TimeZoneImpl*>(&obj);
192 return (*this == *pTimeZoneImpl);
198 _TimeZoneImpl::GetHashCode(void) const
200 int hashCode = GetId().GetHashCode();
201 Integer intValues = GetRawOffset() + GetDstSavings() + GetDstStartingYear() + IsDstUsed();
202 hashCode = (hashCode << 5) - hashCode + intValues.GetHashCode();
203 hashCode = (hashCode << 5) - hashCode + __startingRule.GetHashCode();
204 hashCode = (hashCode << 5) - hashCode + __endingRule.GetHashCode();
210 _TimeZoneImpl::GetId(void) const
212 U_ICU_NAMESPACE::UnicodeString icuStr;
213 return _LocaleData::GetOspString(__icuTimeZone.getID(icuStr));
217 _TimeZoneImpl::SetId(const String& id)
219 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
220 __icuTimeZone.setID(icuStr);
224 _TimeZoneImpl::GetRawOffset(void) const
226 return __icuTimeZone.getRawOffset() / ONE_MIN_IN_MILLISEC;
230 _TimeZoneImpl::SetRawOffset(int rawOffset)
232 __icuTimeZone.setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
236 _TimeZoneImpl::GetDstStartingYear(void) const
238 return __dstStartingYear;
242 _TimeZoneImpl::SetDstStartingYear(int year)
244 __dstStartingYear = year;
245 __icuTimeZone.setStartYear(year);
249 _TimeZoneImpl::GetDstSavings(void) const
251 return __icuTimeZone.getDSTSavings() / ONE_MIN_IN_MILLISEC;
255 _TimeZoneImpl::SetDstSavings(int dstSavings)
257 UErrorCode ec = U_ZERO_ERROR;
258 __icuTimeZone.setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
262 _TimeZoneImpl::GetDstStartingRule(void) const
264 return __startingRule.GetMonth() != MONTH_UNDEFINED ? &__startingRule : null;
268 _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
271 int dayOfWeekInMonth = 0;
276 UErrorCode ec = U_ZERO_ERROR;
277 GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
279 U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
280 __icuTimeZone.setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
281 __startingRule = startRule;
285 _TimeZoneImpl::GetDstEndingRule(void) const
287 return __endingRule.GetMonth() != MONTH_UNDEFINED ? &__endingRule : null;
291 _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
294 int dayOfWeekInMonth = 0;
299 UErrorCode ec = U_ZERO_ERROR;
300 GetIcuTimeRuleValue(endRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
302 U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
303 __icuTimeZone.setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
304 __endingRule = endRule;
308 _TimeZoneImpl::SetDstRules(const TimeRule& startRule, const TimeRule& endRule, int dstSavings)
310 SysTryReturnResult(NID_LCL, dstSavings >= 0,
311 E_OUT_OF_RANGE, "dstSavings [%d] should be greater or equal to than 0", dstSavings);
312 SysTryReturnResult(NID_LCL, dstSavings < ONE_DAY_IN_MINUTE,
313 E_OUT_OF_RANGE, "dstSavings [%d] should be greater than %d", dstSavings, ONE_DAY_IN_MINUTE);
314 SetDstStartingRule(startRule);
315 SetDstEndingRule(endRule);
316 SetDstSavings(dstSavings);
321 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
323 UErrorCode ec = U_ZERO_ERROR;
324 __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
325 rawOffset /= ONE_MIN_IN_MILLISEC;
326 dstOffset /= ONE_MIN_IN_MILLISEC;
327 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
331 _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
335 date.SetValue(ts.GetTicks());
339 UErrorCode ec = U_ZERO_ERROR;
340 __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
341 offset = (rawOffset + dstOffset) / ONE_MIN_IN_MILLISEC;
342 return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
346 _TimeZoneImpl::IsDstUsed(void) const
348 return __icuTimeZone.useDaylightTime();
352 _TimeZoneImpl::GetTimeZoneImpl(const TimeZone& ospTimeZone)
354 return ospTimeZone.__pTimeZoneImpl;
358 _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
360 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
361 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
362 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
364 U_ICU_NAMESPACE::UnicodeString retIcuStr;
365 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
366 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
368 U_ICU_NAMESPACE::SimpleTimeZone icuTimeZone(pIcuTimeZone->getRawOffset(), icuStr);
369 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(icuTimeZone));
372 delete timeZone.__pTimeZoneImpl;
373 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
377 return E_INVALID_ARG;
381 _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Locales::TimeZone& timeZone)
383 U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
384 std::unique_ptr<U_ICU_NAMESPACE::TimeZone> pIcuTimeZone(U_ICU_NAMESPACE::TimeZone::createTimeZone(icuStr));
385 SysTryReturnResult(NID_LCL, pIcuTimeZone != null, E_INVALID_ARG, "Unable to create ICU timezone");
387 U_ICU_NAMESPACE::UnicodeString retIcuStr;
388 SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
389 E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
391 std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(*pIcuTimeZone, _LocaleData::GetIcuDate(utcTime)));
394 delete timeZone.__pTimeZoneImpl;
395 timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
399 return E_INVALID_ARG;
403 _TimeZoneImpl::GetIcuTimeRuleValue(const TimeRule& ospRule, int& month, int& dayOfWeekInMonth, int& dayOfWeek, int& time, int& mode)
405 if (ospRule.GetMonth() != MONTH_UNDEFINED)
407 month = ospRule.GetMonth() - 1;
409 int ospDay = ospRule.GetDay();
410 dayOfWeekInMonth = (ospDay == TimeRule::DAY_UNDEFINED)? 0 : ospDay;
412 int ospDayOfWeek = ospRule.GetDayOfWeek();
413 dayOfWeek = (ospDayOfWeek == WEEK_UNDEFINED)? 0 : ospDayOfWeek;
415 time = ospRule.GetHour() * ONE_HOUR_IN_MILLISEC + ospRule.GetMinute() * ONE_MIN_IN_MILLISEC;
417 int ospTimeMode = ospRule.GetTimeMode();
418 mode = IcuDateTimeRule::WALL_TIME;
419 if (ospTimeMode == Tizen::System::TIME_MODE_UTC)
421 mode = IcuDateTimeRule::UTC_TIME;
424 if (ospTimeMode == Tizen::System::TIME_MODE_STANDARD)
426 mode = IcuDateTimeRule::STANDARD_TIME;
429 switch (ospRule.GetRuleMode())
432 case BACKWARD_FROM_END_OF_MONTH:
435 case DAY_OF_WEEK_IN_MONTH:
436 dayOfWeekInMonth = ospRule.GetWeek();
437 if (dayOfWeekInMonth < 0)
442 case AFTER_THE_SPECIFIED_DAY:
443 case BEFORE_THE_SPECIFIED_DAY:
444 dayOfWeekInMonth *= ospRule.IsOnOrAfterDay()? 1 : -1;
445 dayOfWeek = -dayOfWeek;
452 _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRule* pIcuRule, TimeRule& ospRule)
456 Month month = MONTH_UNDEFINED;
457 int icuMonth = pIcuRule->getRuleMonth();
458 if (icuMonth >= 0 && icuMonth <= 11)
460 month = static_cast< Month > (icuMonth + 1);
463 IcuDateTimeRule::DateRuleType dateRuleType = pIcuRule->getDateRuleType();
464 int day = (dateRuleType == IcuDateTimeRule::DOW)? TimeRule::DAY_UNDEFINED : pIcuRule->getRuleDayOfMonth();
466 Week week = WEEK_UNDEFINED;
467 int icuWeek = pIcuRule->getRuleWeekInMonth();
468 if (dateRuleType == IcuDateTimeRule::DOW)
470 week = (icuWeek == -1)? LAST_WEEK : static_cast< Week >(icuWeek);
473 DayOfWeek dayOfWeek = DAY_OF_WEEK_UNDEFINED;
474 if (dateRuleType != IcuDateTimeRule::DOM)
476 dayOfWeek = static_cast< DayOfWeek >(pIcuRule->getRuleDayOfWeek());
479 bool onOrAfterDay = (dateRuleType == IcuDateTimeRule::DOW_LEQ_DOM)? false : true;
481 int ruleMID = pIcuRule->getRuleMillisInDay();
482 int hour = ruleMID / ONE_HOUR_IN_MILLISEC;
483 int minute = (ruleMID % ONE_HOUR_IN_MILLISEC) / ONE_MIN_IN_MILLISEC;
485 Tizen::System::TimeMode timeMode = Tizen::System::TIME_MODE_WALL;
486 IcuDateTimeRule::TimeRuleType timeRuleType = pIcuRule->getTimeRuleType();
487 if (timeRuleType == IcuDateTimeRule::UTC_TIME)
489 timeMode = Tizen::System::TIME_MODE_UTC;
492 if (timeRuleType == IcuDateTimeRule::STANDARD_TIME)
494 timeMode = Tizen::System::TIME_MODE_STANDARD;
497 ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);