Merge "sync code for tizen_2.2" into devel_3.0_main
[platform/framework/native/appfw.git] / src / locales / FLcl_TimeZoneImpl.cpp
index ab1f8ab..b117542 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
  */
 
 #include <unique_ptr.h>
+#include <unicode/timezone.h>
+#include <unicode/basictz.h>
+#include <unicode/simpletz.h>
+#include <unicode/tztrans.h>
+#include <unicode/tzrule.h>
 
+#include <FBaseInteger.h>
 #include <FBaseSysLog.h>
 #include <FLclTimeZone.h>
 
 #include "FLcl_LocaleData.h"
 #include "FLcl_TimeZoneImpl.h"
 
+typedef U_ICU_NAMESPACE::TimeZone IcuTimeZone;
+typedef U_ICU_NAMESPACE::BasicTimeZone IcuBasicTimeZone;
+typedef U_ICU_NAMESPACE::SimpleTimeZone IcuSimpleTimeZone;
+typedef U_ICU_NAMESPACE::InitialTimeZoneRule IcuInitialTimeZoneRule;
+typedef U_ICU_NAMESPACE::AnnualTimeZoneRule IcuAnnualTimeZoneRule;
+typedef U_ICU_NAMESPACE::DateTimeRule IcuDateTimeRule;
+
+enum DstRuleMode
+{
+       EXACT_DAY = 0,
+       DAY_OF_WEEK_IN_MONTH,
+       AFTER_THE_SPECIFIED_DAY,
+       BEFORE_THE_SPECIFIED_DAY,
+       BACKWARD_FROM_END_OF_MONTH
+};
+
 using namespace Tizen::Base;
 
 namespace Tizen { namespace Locales
 {
 
 _TimeZoneImpl::_TimeZoneImpl(void)
-       : __icuTimeZone(0, "")
+       : __pIcuTimeZone(null)
+       , __dstSaving(60)
        , __dstStartingYear(0)
        , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
        , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
+       , __isCustomizing(true)
 {
-
+       __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(0, "");
+       SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
 }
 
 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id)
-       : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
+       : __pIcuTimeZone(null)
+       , __dstSaving(60)
        , __dstStartingYear(0)
        , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
        , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
+       , __isCustomizing(true)
 {
-
+       UnicodeString icuId(_LocaleData::GetIcuString(id));
+       __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
+       SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
 }
 
 _TimeZoneImpl::_TimeZoneImpl(int rawOffset, const String& id, const TimeRule& startRule, const TimeRule& endRule, int dstOffset)
-       : __icuTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, _LocaleData::GetIcuString(id))
+       : __pIcuTimeZone(null)
+       , __dstSaving(dstOffset)
        , __dstStartingYear(0)
        , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
        , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
+       , __isCustomizing(true)
 {
+       UnicodeString icuId(_LocaleData::GetIcuString(id));
+       __pIcuTimeZone = new U_ICU_NAMESPACE::SimpleTimeZone(rawOffset * ONE_MIN_IN_MILLISEC, icuId);
+       SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
        SetDstRules(startRule, endRule, dstOffset);
 }
 
 _TimeZoneImpl::_TimeZoneImpl(const _TimeZoneImpl& otherTimeZone)
-       : __icuTimeZone(otherTimeZone.__icuTimeZone)
+       : __pIcuTimeZone(null)
+       , __dstSaving(otherTimeZone.__dstSaving)
        , __dstStartingYear(otherTimeZone.__dstStartingYear)
        , __startingRule(otherTimeZone.__startingRule)
        , __endingRule(otherTimeZone.__endingRule)
+       , __isCustomizing(otherTimeZone.__isCustomizing)
 {
+       __pIcuTimeZone = otherTimeZone.__pIcuTimeZone->clone();
+       SysTryReturn(NID_LCL, __pIcuTimeZone, , E_OUT_OF_MEMORY, "It is not enough memory.");
 }
 
-_TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone)
-       : __icuTimeZone(0, "")
+_TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone)
+       : __pIcuTimeZone(null)
+       , __dstSaving(60)
        , __dstStartingYear(0)
        , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
        , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
+       , __isCustomizing(true)
 {
-       U_ICU_NAMESPACE::UnicodeString id;
-       __icuTimeZone.setID(icuTimeZone.getID(id));
-       __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
+       __pIcuTimeZone = pIcuTimeZone;
 }
 
-_TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone& icuTimeZone, UDate icuDate)
-       : __icuTimeZone(0, "")
+_TimeZoneImpl::_TimeZoneImpl(U_ICU_NAMESPACE::TimeZone* pIcuTimeZone, UDate icuDate)
+       : __pIcuTimeZone(null)
+       , __dstSaving(60)
        , __dstStartingYear(0)
        , __startingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
        , __endingRule(MONTH_UNDEFINED, DAY_UNDEFINED)
+       , __isCustomizing(false)
 {
-       U_ICU_NAMESPACE::UnicodeString id;
-       __icuTimeZone.setID(icuTimeZone.getID(id));
-       __icuTimeZone.setRawOffset(icuTimeZone.getRawOffset());
-
-       U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(&icuTimeZone);
+       __pIcuTimeZone = pIcuTimeZone;
+       U_ICU_NAMESPACE::BasicTimeZone* pIcuTz = dynamic_cast<U_ICU_NAMESPACE::BasicTimeZone*>(pIcuTimeZone);
        if (pIcuTz)
        {
-               TimeRule startingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
-               TimeRule endingRule(MONTH_UNDEFINED, DAY_UNDEFINED);
-
-               int dstSaving = 0;
                UErrorCode status = U_ZERO_ERROR;
                U_ICU_NAMESPACE::InitialTimeZoneRule* pInitial = null;
                U_ICU_NAMESPACE::AnnualTimeZoneRule* pStd = null;
                U_ICU_NAMESPACE::AnnualTimeZoneRule* pDst = null;
                pIcuTz->getSimpleRulesNear(icuDate, pInitial, pStd, pDst, status);
+
                if (pStd && pDst)
                {
-                       result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), startingRule);
+                       result r = GetTimeRuleFromIcuDateTimeRule(pDst->getRule(), __startingRule);
                        if (r == E_SUCCESS)
                        {
-                               dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
-                               GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), endingRule);
+                               GetTimeRuleFromIcuDateTimeRule(pStd->getRule(), __endingRule);
+                               __dstStartingYear = pDst->getStartYear();
+                               __dstSaving = pIcuTz->getDSTSavings() / ONE_MIN_IN_MILLISEC;
+                       }
+               }
+               else
+               {
+                       U_ICU_NAMESPACE::TimeZoneTransition transition;
+                       bool result = pIcuTz->getPreviousTransition(icuDate, true, transition);
+                       if (result)
+                       {
+                               const U_ICU_NAMESPACE::TimeZoneRule* pTzFromRule = transition.getFrom();
+                               const U_ICU_NAMESPACE::TimeZoneRule* pTzToRule = transition.getTo();
+
+                               if (pTzFromRule->getDSTSavings())
+                               {
+                                       __dstSaving = pTzFromRule->getDSTSavings() / ONE_MIN_IN_MILLISEC;
+                               }
+                               else if (pTzToRule->getDSTSavings())
+                               {
+                                       __dstSaving = pTzToRule->getDSTSavings() / ONE_MIN_IN_MILLISEC;
+                               }
+                               else //if (pTzFromRule->getDSTSavings() == 0 && pTzToRule->getDSTSavings() == 0)
+                               {
+                                       __dstSaving = 0;
+                               }
                        }
-
-                       int dstStartingYear = pDst->getStartYear();
-                       SetDstStartingYear(dstStartingYear);
                }
-
                delete pInitial;
                delete pStd;
                delete pDst;
-               SetDstRules(startingRule, endingRule, dstSaving);
        }
 }
 
@@ -132,30 +184,35 @@ _TimeZoneImpl::operator =(const _TimeZoneImpl& otherTimeZone)
 {
        if (*this != otherTimeZone)
        {
-               __icuTimeZone = otherTimeZone.__icuTimeZone;
+               __pIcuTimeZone = otherTimeZone.__pIcuTimeZone;
+               __dstSaving = otherTimeZone.__dstSaving;
                __dstStartingYear = otherTimeZone.__dstStartingYear;
                __startingRule = otherTimeZone.__startingRule;
                __endingRule = otherTimeZone.__endingRule;
+               __isCustomizing = otherTimeZone.__isCustomizing;
        }
        return *this;
 }
 
 _TimeZoneImpl::~_TimeZoneImpl(void)
 {
-
+       if (__pIcuTimeZone)
+       {
+               delete __pIcuTimeZone;
+       }
 }
 
-U_ICU_NAMESPACE::SimpleTimeZone
+U_ICU_NAMESPACE::TimeZone*
 _TimeZoneImpl::GetIcuTimeZone(void) const
 {
-       return __icuTimeZone;
+       return __pIcuTimeZone;
 }
 
 
 bool
 _TimeZoneImpl::operator ==(const _TimeZoneImpl& otherTimeZone) const
 {
-       return __icuTimeZone == otherTimeZone.__icuTimeZone;
+       return *__pIcuTimeZone == *otherTimeZone.__pIcuTimeZone;
 }
 
 bool
@@ -179,7 +236,8 @@ int
 _TimeZoneImpl::GetHashCode(void) const
 {
        int hashCode = GetId().GetHashCode();
-       Integer intValues = GetRawOffset() + GetDstSavings() + GetDstStartingYear() + IsDstUsed();
+       int customizing = (__isCustomizing == false) ? 0 : __dstStartingYear;
+       Integer intValues = GetRawOffset() + GetDstSavings() + IsDstUsed() + customizing;
        hashCode = (hashCode << 5) - hashCode + intValues.GetHashCode();
        hashCode = (hashCode << 5) - hashCode + __startingRule.GetHashCode();
        hashCode = (hashCode << 5) - hashCode + __endingRule.GetHashCode();
@@ -191,26 +249,27 @@ String
 _TimeZoneImpl::GetId(void) const
 {
        U_ICU_NAMESPACE::UnicodeString icuStr;
-       return _LocaleData::GetOspString(__icuTimeZone.getID(icuStr));
+       __pIcuTimeZone->getID(icuStr);
+       return _LocaleData::GetOspString(icuStr);
 }
 
 void
 _TimeZoneImpl::SetId(const String& id)
 {
        U_ICU_NAMESPACE::UnicodeString icuStr = _LocaleData::GetIcuString(id);
-       __icuTimeZone.setID(icuStr);
+       __pIcuTimeZone->setID(icuStr);
 }
 
 int
 _TimeZoneImpl::GetRawOffset(void) const
 {
-       return __icuTimeZone.getRawOffset() / ONE_MIN_IN_MILLISEC;
+       return __pIcuTimeZone->getRawOffset() / ONE_MIN_IN_MILLISEC;
 }
 
 void
 _TimeZoneImpl::SetRawOffset(int rawOffset)
 {
-       __icuTimeZone.setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
+       __pIcuTimeZone->setRawOffset(rawOffset * ONE_MIN_IN_MILLISEC);
 }
 
 int
@@ -223,20 +282,51 @@ void
 _TimeZoneImpl::SetDstStartingYear(int year)
 {
        __dstStartingYear = year;
-       __icuTimeZone.setStartYear(year);
+       U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
+
+       if (pStz == null)
+       {
+               U_ICU_NAMESPACE::UnicodeString id;
+               __pIcuTimeZone->getID(id);
+               pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
+               SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
+               delete __pIcuTimeZone;
+               __pIcuTimeZone = pStz;
+       }
+
+       pStz->setStartYear(year);
+       __isCustomizing = true;
 }
 
 int
 _TimeZoneImpl::GetDstSavings(void) const
 {
-       return __icuTimeZone.getDSTSavings() / ONE_MIN_IN_MILLISEC;
+       if (__isCustomizing)
+       {
+               return __pIcuTimeZone->getDSTSavings() / ONE_MIN_IN_MILLISEC;
+       }
+       return __dstSaving;
 }
 
 void
 _TimeZoneImpl::SetDstSavings(int dstSavings)
 {
        UErrorCode ec = U_ZERO_ERROR;
-       __icuTimeZone.setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
+
+       U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
+
+       if (pStz == null)
+       {
+               U_ICU_NAMESPACE::UnicodeString id;
+               __pIcuTimeZone->getID(id);
+               pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
+               SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
+               delete __pIcuTimeZone;
+                __pIcuTimeZone = pStz;
+       }
+       pStz->setDSTSavings(dstSavings * ONE_MIN_IN_MILLISEC, ec);
+       __dstSaving = dstSavings;
+       __isCustomizing = true;
 }
 
 const TimeRule*
@@ -258,8 +348,21 @@ _TimeZoneImpl::SetDstStartingRule(const TimeRule& startRule)
        GetIcuTimeRuleValue(startRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
 
        U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
-       __icuTimeZone.setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
+       U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
+
+       if (pStz == null)
+       {
+               U_ICU_NAMESPACE::UnicodeString id;
+               __pIcuTimeZone->getID(id);
+               pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
+               SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
+               delete __pIcuTimeZone;
+               __pIcuTimeZone = pStz;
+       }
+
+       pStz->setStartRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
        __startingRule = startRule;
+       __isCustomizing = true;
 }
 
 const TimeRule*
@@ -281,8 +384,21 @@ _TimeZoneImpl::SetDstEndingRule(const TimeRule& endRule)
        GetIcuTimeRuleValue(endRule, month, dayOfWeekInMonth, dayOfWeek, time, mode);
 
        U_ICU_NAMESPACE::SimpleTimeZone::TimeMode timeMode = static_cast<U_ICU_NAMESPACE::SimpleTimeZone::TimeMode> (mode);
-       __icuTimeZone.setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
+       U_ICU_NAMESPACE::SimpleTimeZone* pStz = dynamic_cast<U_ICU_NAMESPACE::SimpleTimeZone*>(__pIcuTimeZone);
+
+       if (pStz == null)
+       {
+               U_ICU_NAMESPACE::UnicodeString id;
+               __pIcuTimeZone->getID(id);
+               pStz = new U_ICU_NAMESPACE::SimpleTimeZone(__pIcuTimeZone->getRawOffset(), id);
+               SysTryReturn(NID_LCL, pStz, ,E_OUT_OF_MEMORY, "It is not enough memory.");
+               delete __pIcuTimeZone;
+               __pIcuTimeZone = pStz;
+       }
+
+       pStz->setEndRule(month, dayOfWeekInMonth, dayOfWeek, time, timeMode, ec);
        __endingRule = endRule;
+       __isCustomizing = true;
 }
 
 result
@@ -302,7 +418,7 @@ result
 _TimeZoneImpl::GetOffset(const DateTime& date, bool local, int& rawOffset, int& dstOffset) const
 {
        UErrorCode ec = U_ZERO_ERROR;
-       __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
+       __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), local, rawOffset, dstOffset, ec);
        rawOffset /= ONE_MIN_IN_MILLISEC;
        dstOffset /= ONE_MIN_IN_MILLISEC;
        return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
@@ -313,12 +429,13 @@ _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
 {
        TimeSpan ts(ticks);
        DateTime date;
-       date.SetValue(ts.GetTicks());
+       result r = date.SetValue(ts.GetTicks());
+       SysTryReturnResult(NID_LCL, r == E_SUCCESS, E_INVALID_ARG, "It is an invalid argument.");
 
        int rawOffset = 0;
        int dstOffset = 0;
        UErrorCode ec = U_ZERO_ERROR;
-       __icuTimeZone.getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
+       __pIcuTimeZone->getOffset(_LocaleData::GetIcuDate(date), false, rawOffset, dstOffset, ec);
        offset = (rawOffset + dstOffset) / ONE_MIN_IN_MILLISEC;
        return U_SUCCESS(ec) ? E_SUCCESS : E_INVALID_ARG;
 }
@@ -326,7 +443,7 @@ _TimeZoneImpl::GetOffset(long long ticks, int& offset) const
 bool
 _TimeZoneImpl::IsDstUsed(void) const
 {
-       return __icuTimeZone.useDaylightTime();
+       return __pIcuTimeZone->useDaylightTime();
 }
 
 const _TimeZoneImpl*
@@ -346,16 +463,15 @@ _TimeZoneImpl::GetTimeZone(const String& id, Tizen::Locales::TimeZone& timeZone)
        SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
                                E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
 
-       U_ICU_NAMESPACE::SimpleTimeZone icuTimeZone(pIcuTimeZone->getRawOffset(), icuStr);
-       std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(icuTimeZone));
-       if (pTimeZoneImpl)
-       {
-               delete timeZone.__pTimeZoneImpl;
-               timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
-               return E_SUCCESS;
-       }
+       std::unique_ptr<U_ICU_NAMESPACE::SimpleTimeZone> pIcuSimpleTimeZone(new U_ICU_NAMESPACE::SimpleTimeZone(pIcuTimeZone->getRawOffset(), icuStr));
+       SysTryReturnResult(NID_LCL, pIcuSimpleTimeZone, E_OUT_OF_MEMORY, "It is enough memory.");
+       std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuSimpleTimeZone.get()));
+       SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
 
-       return E_INVALID_ARG;
+       delete timeZone.__pTimeZoneImpl;
+       timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
+       pIcuSimpleTimeZone.release();
+       return E_SUCCESS;
 }
 
 result
@@ -369,15 +485,13 @@ _TimeZoneImpl::GetTimeZone(const String& id, const DateTime& utcTime, Tizen::Loc
        SysTryReturnResult(NID_LCL, pIcuTimeZone->getID(retIcuStr) == icuStr,
                                E_INVALID_ARG, "Unsupported timezone id [%ls]", id.GetPointer());
 
-       std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(*pIcuTimeZone, _LocaleData::GetIcuDate(utcTime)));
-       if (pTimeZoneImpl)
-       {
-               delete timeZone.__pTimeZoneImpl;
-               timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
-               return E_SUCCESS;
-       }
+       std::unique_ptr<_TimeZoneImpl> pTimeZoneImpl(new (std::nothrow) _TimeZoneImpl(pIcuTimeZone.get(), _LocaleData::GetIcuDate(utcTime)));
+       SysTryReturnResult(NID_LCL, pTimeZoneImpl, E_OUT_OF_MEMORY, "It is enough memory.");
 
-       return E_INVALID_ARG;
+       delete timeZone.__pTimeZoneImpl;
+       timeZone.__pTimeZoneImpl = pTimeZoneImpl.release();
+       pIcuTimeZone.release();
+       return E_SUCCESS;
 }
 
 void
@@ -477,7 +591,6 @@ _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRul
 
                ospRule.SetValue(month, day, week, dayOfWeek, onOrAfterDay, hour, minute, timeMode);
 
-
                return E_SUCCESS;
        }
 
@@ -486,6 +599,3 @@ _TimeZoneImpl::GetTimeRuleFromIcuDateTimeRule(const U_ICU_NAMESPACE::DateTimeRul
 
 };
 };      // Tizen::Locales
-
-
-